Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion apps/www/src/app/examples/datatable/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -423,10 +423,24 @@ const columns: DataTableColumnDef<(typeof sampleData)[number], unknown>[] = [
{
accessorKey: 'team',
header: 'Team',
enableColumnFilter: true,
filterType: 'multiselect' as const,
enableGrouping: true,
showGroupCount: true,
enableSorting: true,
enableHiding: true
enableHiding: true,
filterOptions: [
{ value: 'Frontend', label: 'Frontend' },
{ value: 'Backend', label: 'Backend' },
{ value: 'Design', label: 'Design' },
{ value: 'DevOps', label: 'DevOps' },
{ value: 'Content', label: 'Content' },
{ value: 'Growth', label: 'Growth' },
{ value: 'East', label: 'East' },
{ value: 'West', label: 'West' },
{ value: 'Tier 1', label: 'Tier 1' },
{ value: 'Tier 2', label: 'Tier 2' }
]
},
{
accessorKey: 'location',
Expand Down
49 changes: 27 additions & 22 deletions apps/www/src/app/examples/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
import dayjs from 'dayjs';
import React, { useState } from 'react';

/** Kitchen-sink examples route rendering Apsara components for manual QA. */
const Page = () => {
const [dialogOpen, setDialogOpen] = useState(false);
const [nestedDialogOpen, setNestedDialogOpen] = useState(false);
Expand Down Expand Up @@ -274,18 +275,20 @@ const Page = () => {
dateFormat='D MMM YYYY'
value={dayjs().add(16, 'year').toDate()}
onSelect={(value: Date) => console.log(value)}
calendarProps={{
captionLayout: 'dropdown',
startMonth: dayjs().add(3, 'month').toDate(),
endMonth: dayjs().add(4, 'year').toDate(),
disabled: {
before: dayjs().add(3, 'month').toDate(),
after: dayjs().add(3, 'year').toDate()
slotProps={{
calendar: {
captionLayout: 'dropdown',
startMonth: dayjs().add(3, 'month').toDate(),
endMonth: dayjs().add(4, 'year').toDate(),
disabled: {
before: dayjs().add(3, 'month').toDate(),
after: dayjs().add(3, 'year').toDate()
}
},
input: {
size: 'small'
}
}}
inputProps={{
size: 'small'
}}
/>

<RangePicker
Expand All @@ -297,18 +300,18 @@ const Page = () => {
to: range.to ?? new Date()
})
}
calendarProps={{
captionLayout: 'dropdown',
numberOfMonths: 2,
startMonth: dayjs('2024-01-01').toDate(),
endMonth: dayjs('2027-12-01').toDate(),
defaultMonth: dayjs('2027-11-01').toDate()
}}
inputsProps={{
startDate: {
slotProps={{
calendar: {
captionLayout: 'dropdown',
numberOfMonths: 2,
startMonth: dayjs('2024-01-01').toDate(),
endMonth: dayjs('2027-12-01').toDate(),
defaultMonth: dayjs('2027-11-01').toDate()
},
startInput: {
size: 'small'
},
endDate: {
endInput: {
size: 'small'
}
}}
Expand All @@ -323,8 +326,10 @@ const Page = () => {
/>

<DatePicker
calendarProps={{
captionLayout: 'dropdown'
slotProps={{
calendar: {
captionLayout: 'dropdown'
}
}}
/>

Expand Down
5 changes: 3 additions & 2 deletions apps/www/src/components/playground/calendar-examples.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
import { Calendar, DatePicker, Flex, RangePicker } from '@raystack/apsara';
import PlaygroundLayout from './playground-layout';

/** Playground showcase for `Calendar`, `DatePicker`, and `RangePicker` using the `slotProps` API. */
export function CalendarExamples() {
return (
<PlaygroundLayout title='Calendar'>
<Flex gap={5} direction='column'>
<Calendar numberOfMonths={2} />
<RangePicker inputsProps={{ startDate: { size: 'small' } }} />
<DatePicker inputProps={{ size: 'small' }} />
<RangePicker slotProps={{ startInput: { size: 'small' } }} />
<DatePicker slotProps={{ input: { size: 'small' } }} />
</Flex>
</PlaygroundLayout>
);
Expand Down
16 changes: 13 additions & 3 deletions apps/www/src/components/playground/filter-chip-examples.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,19 @@ export function FilterChipExamples() {
{ label: 'Inactive', value: 'inactive' }
]}
/>
<FilterChip label='Date' leadingIcon={<Info />} columnType='date' />
<FilterChip label='Date' leadingIcon={<Info />} columnType='string' />
<FilterChip label='Date' leadingIcon={<Info />} columnType='number' />
<FilterChip
label='Team'
leadingIcon={<Info />}
columnType='multiselect'
options={[
{ label: 'Frontend', value: 'frontend' },
{ label: 'Backend', value: 'backend' },
{ label: 'Design', value: 'design' }
]}
/>
<FilterChip label='Created' leadingIcon={<Info />} columnType='date' />
<FilterChip label='Name' leadingIcon={<Info />} columnType='string' />
<FilterChip label='Amount' leadingIcon={<Info />} columnType='number' />
</Flex>
</PlaygroundLayout>
);
Expand Down
4 changes: 2 additions & 2 deletions apps/www/src/content/docs/components/calendar/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export interface RangePickerProps {
* - With spaces: "DD MMM YYYY", "MMM DD YYYY", "YYYY MMM DD"
* - With full month: "DD MMMM YYYY", "MMMM DD YYYY", "YYYY MMMM DD"
* - For more supported formats, refer to https://day.js.org/docs/en/display/format
* @defaultValue "DD/MM/YYYY"
* @defaultValue "DD MMM YYYY"
*/
dateFormat?: string;

Expand Down Expand Up @@ -229,7 +229,7 @@ export interface DatePickerProps {
* - With dots: "DD.MM.YYYY", "MM.DD.YYYY", "YYYY.MM.DD"
* - With spaces: "DD MMM YYYY", "MMM DD YYYY", "YYYY MMM DD"
* - With full month: "DD MMMM YYYY", "MMMM DD YYYY", "YYYY MMMM DD"
* @defaultValue "DD/MM/YYYY"
* @defaultValue "DD MMM YYYY"
*/
dateFormat?: string;

Expand Down
4 changes: 3 additions & 1 deletion apps/www/src/content/docs/components/datatable/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ interface DataTableColumnDef<TData, TValue> {
enableColumnFilter?: boolean; // Enable filtering
enableHiding?: boolean; // Enable column visibility toggle
enableGrouping?: boolean; // Enable grouping
filterOptions?: FilterSelectOption[]; // Options for select filter
filterType?: "string" | "number" | "select" | "multiselect" | "date"; // Filter input type
filterOptions?: FilterSelectOption[]; // Options for select/multiselect filters
defaultHidden?: boolean; // Hide column by default
}
```
Expand All @@ -174,6 +175,7 @@ Filter types:
- Number: equals, not equals, less than, less than or equal, greater than, greater than or equal
- Date: equals, not equals, before, on or before, after, on or after
- Select: equals, not equals
- Multiselect: is any of, is none of (value is a `string[]`)

### Sorting

Expand Down
29 changes: 27 additions & 2 deletions apps/www/src/content/docs/components/datatable/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,15 @@ export interface DataTableColumnDef<TData, TValue> {
/** Enable grouping */
enableGrouping?: boolean;

/** Options for select filter */
/** Type of filter input rendered in the filter chip
* @default "string"
*/
filterType?: 'string' | 'number' | 'select' | 'multiselect' | 'date';

/** Options for select and multiselect filters */
filterOptions?: FilterSelectOption[];

/** Props forwarded to filter components by type. Refer to Select component for full props list. */
/** Props forwarded to filter components by type. Refer to Select and DatePicker for full props lists. */
filterProps?: {
select?: {
autocomplete?: boolean;
Expand All @@ -104,6 +109,16 @@ export interface DataTableColumnDef<TData, TValue> {
searchValue?: string;
defaultSearchValue?: string;
};
calendar?: {
dateFormat?: string;
showCalendarIcon?: boolean;
timeZone?: string;
slotProps?: {
input?: Record<string, unknown>;
calendar?: Record<string, unknown>;
popover?: Record<string, unknown>;
};
};
};

/** Hide column by default */
Expand All @@ -126,6 +141,16 @@ export interface FiltersProps {
availableFilters: DataTableColumn<TData, TValue>[];
appliedFilters: Set<string>;
}) => ReactNode);

/** Additional CSS class names for the filters container */
className?: string;

/** Class names for inner elements. `addFilter` applies to the default
* add-filter triggers only — a custom `trigger` styles itself. */
classNames?: {
filterChips?: string;
addFilter?: string;
};
}
export interface DataTableContentProps {
/**
Expand Down
27 changes: 20 additions & 7 deletions apps/www/src/content/docs/components/filter-chip/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const getCode = (props: ComponentPropsType) => {
const { onRemove, ...rest } = props;
const onRemoveProp = onRemove ? `onRemove={() => alert("Removed")}` : '';

if (props.columnType === 'select')
if (props.columnType === 'select' || props.columnType === 'multiselect')
return `
<FilterChip${getPropsString(rest)}
options={[
Expand All @@ -24,7 +24,7 @@ export const playground = {
controls: {
columnType: {
type: 'select',
options: ['select', 'date', 'string', 'number'],
options: ['select', 'multiselect', 'date', 'string', 'number'],
defaultValue: 'string'
},
variant: {
Expand Down Expand Up @@ -62,19 +62,17 @@ export const inputDemo = {
/>`
},
{
name: 'Select with Autocomplete',
name: 'Multiselect',
code: `
<FilterChip
label="Status"
leadingIcon={<Info />}
columnType="select"
columnType="multiselect"
options={[
{ label: "Active", value: "active" },
{ label: "Inactive", value: "inactive" },
{ label: "Pending", value: "pending" },
{ label: "Archived", value: "archived" }
{ label: "Pending", value: "pending" }
]}
selectProps={{ autocomplete: true }}
/>`
},
{
Expand Down Expand Up @@ -123,6 +121,21 @@ export const autocompleteDemo = {
selectProps={{ autocomplete: true }}
/>`
};
export const calendarPropsDemo = {
type: 'code',
code: `
<FilterChip
label="Created"
leadingIcon={<Info />}
columnType="date"
calendarProps={{
dateFormat: "YYYY-MM-DD",
slotProps: {
calendar: { captionLayout: "dropdown" }
}
}}
/>`
};
export const iconDemo = {
type: 'code',
code: `
Expand Down
10 changes: 8 additions & 2 deletions apps/www/src/content/docs/components/filter-chip/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: A compact, interactive element for filtering data with various inpu
source: packages/raystack/components/filter-chip
---

import { playground, inputDemo, autocompleteDemo, iconDemo, actionDemo, operationsDemo } from "./demo.ts";
import { playground, inputDemo, autocompleteDemo, calendarPropsDemo, iconDemo, actionDemo, operationsDemo } from "./demo.ts";

<Demo data={playground} />

Expand All @@ -28,7 +28,7 @@ Renders an interactive chip for filtering content.

### Input Types

FilterChip supports four different input types to handle various filtering needs.
FilterChip supports five input types — `select`, `multiselect`, `date`, `string`, and `number` — to handle various filtering needs. `multiselect` takes a `string[]` value and summarizes two or more selections as "N selected".

<Demo data={inputDemo} />

Expand All @@ -38,6 +38,12 @@ Use `selectProps` to enable autocomplete search on select and multiselect filter

<Demo data={autocompleteDemo} />

### Date with calendarProps

Use `calendarProps` to forward DatePicker options — `dateFormat`, `timeZone`, `slotProps.calendar`, etc. — to the chip's date control. `value`, `onSelect`, and `defaultValue` are owned by `FilterChip`, and `children` is excluded so the chip's input trigger isn't replaced.

<Demo data={calendarPropsDemo} />

### With Leading Icon

FilterChip can display an icon before the label to provide visual context.
Expand Down
30 changes: 23 additions & 7 deletions apps/www/src/content/docs/components/filter-chip/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,31 @@ export interface FilterChipProps {
/** Text label for the filter (required) */
label: string;

/** Current value of the filter */
value?: string;
/** Current value of the filter. `multiselect` takes a `string[]`; `date`
* takes a `Date` (a string or epoch number is parsed for you). */
value?: string | string[] | number | Date;

/** Type of input for the filter
* @default "string"
*/
columnType?: 'select' | 'date' | 'string' | 'number';
columnType?: 'select' | 'multiselect' | 'date' | 'string' | 'number';

/** Filterchip variant
* @default "default"
*/
variant?: 'default' | 'text';

/** Array of options for the select type input */
/** Array of options for the select and multiselect type inputs */
options?: { label: string; value: string }[];

/** Optional array of operations for the type of filter oepration */
/** Optional array of operations for the type of filter operation */
operations?: { label: string; value: string }[];

/** Callback when the filter value changes */
onValueChange?: (value: string) => void;
/** Callback when the filter value changes; receives the value and the active operation */
onValueChange?: (
value: string | string[] | number | Date,
operation: string
) => void;

/** Callback when the filter operation changes */
onOperationChange?: (operation: string) => void;
Expand All @@ -42,6 +46,18 @@ export interface FilterChipProps {
defaultSearchValue?: string;
};

/** Props forwarded to the underlying DatePicker for `columnType="date"`. Refer to DatePicker for full props list. `dateFormat` defaults to `"DD MMM YYYY"`. */
calendarProps?: {
dateFormat?: string;
showCalendarIcon?: boolean;
timeZone?: string;
slotProps?: {
input?: Record<string, unknown>;
calendar?: Record<string, unknown>;
popover?: Record<string, unknown>;
};
};

/** Additional CSS class names */
className?: string;
}
Loading
Loading