@alfakit/react 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/components/actions/action-button.d.ts.map +1 -1
- package/dist/components/actions/action-button.js +5 -4
- package/dist/components/actions/action-button.js.map +1 -1
- package/dist/components/actions/action-modals.d.ts.map +1 -1
- package/dist/components/actions/action-modals.js +2 -5
- package/dist/components/actions/action-modals.js.map +1 -1
- package/dist/components/fields/color-picker.js +1 -0
- package/dist/components/fields/color-picker.js.map +1 -1
- package/dist/components/fields/file-upload.js +11 -10
- package/dist/components/fields/file-upload.js.map +1 -1
- package/dist/components/fields/one-time-code-input.js +1 -1
- package/dist/components/fields/one-time-code-input.js.map +1 -1
- package/dist/components/fields/repeater-table.js +12 -1
- package/dist/components/fields/repeater-table.js.map +1 -1
- package/dist/components/fields/select.js +3 -3
- package/dist/components/fields/select.js.map +1 -1
- package/dist/components/file-manager/file-manager.js +1 -1
- package/dist/components/file-manager/file-manager.js.map +1 -1
- package/dist/components/form/form-block.d.ts.map +1 -1
- package/dist/components/form/form-block.js +13 -1
- package/dist/components/form/form-block.js.map +1 -1
- package/dist/components/form/form-context.js +6 -2
- package/dist/components/form/form-context.js.map +1 -1
- package/dist/components/layout/fused-group.js +1 -0
- package/dist/components/layout/fused-group.js.map +1 -1
- package/dist/components/layout/tabs.d.ts.map +1 -1
- package/dist/components/layout/tabs.js +54 -15
- package/dist/components/layout/tabs.js.map +1 -1
- package/dist/components/panel/global-search.js +1 -0
- package/dist/components/panel/global-search.js.map +1 -1
- package/dist/components/panel/shortcut-keys.js +1 -0
- package/dist/components/panel/shortcut-keys.js.map +1 -1
- package/dist/components/panel/tenant-menu.js +2 -2
- package/dist/components/panel/tenant-menu.js.map +1 -1
- package/dist/components/table/cells.js +9 -1
- package/dist/components/table/cells.js.map +1 -1
- package/dist/components/table/grouping.js +11 -1
- package/dist/components/table/grouping.js.map +1 -1
- package/dist/components.css +347 -0
- package/dist/eject-manifest.json +2 -2
- package/dist/standalone/alfakit-toaster.d.ts.map +1 -1
- package/dist/standalone/alfakit-toaster.js +8 -1
- package/dist/standalone/alfakit-toaster.js.map +1 -1
- package/dist/standalone.css +47 -0
- package/dist/starter-kit/widgets-loaded.js +1 -1
- package/dist/starter-kit/widgets-loaded.js.map +1 -1
- package/dist/starter-kit/widgets-triggers.js +1 -0
- package/dist/starter-kit/widgets-triggers.js.map +1 -1
- package/dist/themes.css +2 -334
- package/package.json +2 -2
- package/src/components/actions/action-button.tsx +7 -4
- package/src/components/actions/action-modals.tsx +3 -1
- package/src/components/fields/color-picker.tsx +1 -0
- package/src/components/fields/file-upload.tsx +21 -10
- package/src/components/fields/one-time-code-input.tsx +1 -1
- package/src/components/fields/repeater-table.tsx +12 -1
- package/src/components/fields/select.tsx +7 -3
- package/src/components/file-manager/file-manager.tsx +1 -1
- package/src/components/form/form-block.tsx +24 -0
- package/src/components/form/form-context.tsx +2 -5
- package/src/components/layout/fused-group.tsx +5 -1
- package/src/components/layout/tabs.tsx +72 -17
- package/src/components/panel/global-search.tsx +1 -1
- package/src/components/panel/shortcut-keys.tsx +4 -1
- package/src/components/panel/tenant-menu.tsx +2 -2
- package/src/components/table/cells.tsx +18 -3
- package/src/components/table/grouping.tsx +15 -1
- package/src/standalone/alfakit-toaster.tsx +21 -2
- package/src/starter-kit/widgets-loaded.tsx +1 -1
- package/src/starter-kit/widgets-triggers.tsx +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cells.js","names":[],"sources":["../../../src/components/table/cells.tsx"],"sourcesContent":["import type {\n CellSchema,\n ColorColumnSchema,\n ColumnSchema,\n IconColumnSchema,\n Option,\n OptionOrGroup,\n RecordKey,\n SelectColumnSchema,\n TextInputColumnSchema,\n ToggleColumnSchema,\n ViewColumnSchema,\n} from '@alfakit/core'\nimport {\n columnRegistryKey,\n filterSelectColumnOptions,\n isOptionGroup,\n optionText,\n remainingTextSizeClass,\n resolvePartialProps,\n searchTableColumnOptions,\n selectColumnEmptyMessage,\n stackedImageStyle,\n updateTableCell,\n usesDefaultImageStack,\n} from '@alfakit/core'\nimport { router } from '@inertiajs/react'\nimport { CheckIcon, ChevronsUpDownIcon } from 'lucide-react'\nimport { createElement, useEffect, useRef, useState } from 'react'\nimport { usePanel, useRegistry, useT } from '../../context'\nimport { extraProps } from '../../lib/attributes'\nimport {\n colorClass,\n iconSizeClasses,\n switchOffColorClasses,\n switchOnColorClasses,\n textColorClasses,\n} from '../../lib/colors'\nimport { Icon } from '../../lib/icons'\nimport { cn } from '../../lib/utils'\nimport { FormattedText } from '../entries/text-entry'\nimport { Button } from '../ui/button'\nimport { Checkbox } from '../ui/checkbox'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '../ui/command'\nimport { Input } from '../ui/input'\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover'\nimport { Spinner } from '../ui/spinner'\nimport { Switch } from '../ui/switch'\n\nexport interface CellProps {\n column: ColumnSchema\n cell: CellSchema\n recordKey: RecordKey\n token: string\n component: string\n}\n\nexport function TableCellContent(props: CellProps) {\n const { column } = props\n // A component registered as `column:<type>` replaces the built-in cell renderer.\n const Custom = useRegistry().resolve(columnRegistryKey(column))\n\n if (Custom) {\n return createElement(Custom, props)\n }\n\n switch (column.type) {\n case 'IconColumn':\n return <IconCell {...props} />\n case 'ImageColumn':\n return <ImageCell {...props} />\n case 'ColorColumn':\n return <ColorCell {...props} />\n case 'ToggleColumn':\n case 'CheckboxColumn':\n return <BooleanCell {...props} />\n case 'SelectColumn':\n return <SelectCell {...props} />\n case 'TextInputColumn':\n return <TextInputCell {...props} />\n case 'ViewColumn':\n return <ViewCell {...props} />\n default:\n return <TextCell {...props} />\n }\n}\n\n/** `IconColumn`: one icon, or one per item of a list state (`wrap()` lets them wrap). */\nfunction IconCell({ column, cell }: CellProps) {\n const icons = cell.icons ?? (cell.icon ? [{ icon: cell.icon, color: cell.color }] : [])\n const sizeClass = colorClass(iconSizeClasses, cell.size, 'md')\n\n if (icons.length === 0) {\n return <span className=\"text-muted-foreground\">—</span>\n }\n\n if (!cell.icons) {\n return (\n <Icon\n name={icons[0]!.icon}\n className={cn(sizeClass, icons[0]!.color && textColorClasses[icons[0]!.color])}\n />\n )\n }\n\n return (\n <div\n data-slot=\"icon-column-icons\"\n className={cn(\n 'flex items-center gap-1.5',\n (column as IconColumnSchema).wrap ? 'flex-wrap' : 'flex-nowrap',\n )}\n >\n {icons.map((item, index) => (\n <Icon\n key={index}\n name={item.icon}\n className={cn(sizeClass, item.color && textColorClasses[item.color])}\n />\n ))}\n </div>\n )\n}\n\n/** `ViewColumn`: the application component registered under the column's `view()` name. */\nfunction ViewCell(props: CellProps) {\n const t = useT()\n const name = (props.column as ViewColumnSchema).component ?? ''\n const Custom = useRegistry().resolve(name)\n\n if (!name || !Custom) {\n return (\n <span className=\"text-destructive text-xs\">\n {t('component_not_registered', { component: name }, `Component ${name} is not registered.`)}\n </span>\n )\n }\n\n return createElement(Custom, { ...(props.cell.props ?? {}), state: props.cell.state, ...props })\n}\n\nfunction TextCell({ column, cell }: CellProps) {\n const text = (\n <FormattedText\n value={cell.state}\n schema={{\n ...(column as object),\n color: cell.color,\n icon: cell.icon,\n iconPosition: cell.iconPosition,\n iconColor: cell.iconColor,\n itemColors: cell.itemColors,\n itemIcons: cell.itemIcons,\n itemUrls: cell.itemUrls,\n }}\n />\n )\n const description = cell.description ? (\n <span className=\"text-muted-foreground block text-xs\">{cell.description}</span>\n ) : null\n const position =\n (column as { descriptionPosition?: 'above' | 'below' }).descriptionPosition ?? 'below'\n\n return (\n <div className=\"flex flex-col gap-0.5\">\n {position === 'above' && description}\n {text}\n {position === 'below' && description}\n </div>\n )\n}\n\nfunction ImageCell({ column, cell }: CellProps) {\n const urls = Array.isArray(cell.state) ? (cell.state as string[]) : []\n const schema = column as {\n circular?: boolean\n square?: boolean\n size?: number | string\n height?: number | string\n width?: string\n stacked?: boolean\n limit?: number\n limitedRemainingText?: boolean\n limitedRemainingTextSize?: string\n wrap?: boolean\n ring?: number\n overlap?: number\n }\n const limit = schema.limit ?? urls.length\n const size = schema.size ?? 40\n\n if (urls.length === 0) {\n return <span className=\"text-muted-foreground\">—</span>\n }\n\n return (\n <div\n className={cn(\n 'flex items-center',\n schema.wrap && 'flex-wrap',\n schema.stacked ? usesDefaultImageStack(schema) && '-space-x-2' : 'gap-1.5',\n schema.wrap && schema.stacked && 'gap-y-1.5',\n )}\n >\n {urls.slice(0, limit).map((url, index) => (\n <img\n key={index}\n src={url}\n alt={cell.alt ?? ''}\n style={{\n height: schema.height ?? size,\n width: schema.width ?? (schema.square || schema.circular ? size : undefined),\n ...stackedImageStyle(index, schema),\n }}\n {...extraProps(\n cell.extraImgAttributes,\n cn(\n 'object-cover',\n schema.circular ? 'rounded-full' : 'rounded-md',\n schema.stacked && usesDefaultImageStack(schema) && 'ring-background ring-2',\n ),\n )}\n />\n ))}\n {schema.limitedRemainingText && urls.length > limit && (\n <span\n data-slot=\"image-remaining\"\n className={cn(\n 'text-muted-foreground ms-1',\n remainingTextSizeClass(schema.limitedRemainingTextSize),\n )}\n >\n +{urls.length - limit}\n </span>\n )}\n </div>\n )\n}\n\nfunction ColorCell({ column, cell }: CellProps) {\n const t = useT()\n const schema = column as ColorColumnSchema\n const [copied, setCopied] = useState<string | null>(null)\n const colors = Array.isArray(cell.state)\n ? (cell.state as string[])\n : cell.state\n ? [String(cell.state)]\n : []\n\n if (colors.length === 0) {\n return <span className=\"text-muted-foreground\">—</span>\n }\n\n const copy = (color: string) => {\n void navigator.clipboard?.writeText(color).then(() => {\n setCopied(color)\n setTimeout(() => setCopied(null), schema.copyMessageDuration ?? 1500)\n })\n }\n\n return (\n <div className={cn('flex items-center gap-1.5', schema.wrap ? 'flex-wrap' : 'flex-nowrap')}>\n {colors.map((color) =>\n schema.copyable ? (\n <button\n key={color}\n type=\"button\"\n data-slot=\"color-copy\"\n title={color}\n aria-label={`${t('copy', {}, 'Copy')} ${color}`}\n className=\"focus-visible:ring-ring/50 inline-flex rounded outline-none focus-visible:ring-[3px]\"\n onClick={(event) => {\n // The cell may sit inside a link or a clickable row.\n event.preventDefault()\n event.stopPropagation()\n copy(color)\n }}\n >\n <span\n className=\"inline-flex size-5 items-center justify-center rounded border shadow-xs\"\n style={{ backgroundColor: color }}\n >\n {copied === color && <CheckIcon className=\"size-3 text-white mix-blend-difference\" />}\n </span>\n </button>\n ) : (\n <span\n key={color}\n title={color}\n className=\"size-5 rounded border shadow-xs\"\n style={{ backgroundColor: color }}\n />\n ),\n )}\n {schema.copyable && copied && (\n <span role=\"status\" className={cn('text-xs', !schema.copyMessage && 'sr-only')}>\n {schema.copyMessage ?? t('copied', {}, 'Copied')}\n </span>\n )}\n </div>\n )\n}\n\nfunction useCellUpdate({ recordKey, column, token, component }: CellProps) {\n const panel = usePanel()\n const [saving, setSaving] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const update = async (state: unknown) => {\n if (!panel.endpoints.tableCell || !panel.endpoints.tableReorder) return\n\n setSaving(true)\n setError(null)\n\n try {\n await updateTableCell(\n { cell: panel.endpoints.tableCell, reorder: panel.endpoints.tableReorder },\n token,\n component,\n recordKey,\n column.name,\n state,\n )\n router.reload({ only: resolvePartialProps(['page']) })\n } catch (caught) {\n const errors = (caught as { errors?: Record<string, string[]> }).errors\n setError(errors?.state?.[0] ?? (caught as Error).message)\n } finally {\n setSaving(false)\n }\n }\n\n return { update, saving, error }\n}\n\nfunction BooleanCell(props: CellProps) {\n const { column, cell } = props\n const { update, saving } = useCellUpdate(props)\n const [checked, setChecked] = useState(Boolean(cell.state))\n const disabled = Boolean(cell.disabled) || saving\n const toggle = column as ToggleColumnSchema\n\n const onChange = (next: boolean) => {\n setChecked(next)\n void update(next)\n }\n\n if (column.type === 'CheckboxColumn') {\n return (\n <Checkbox\n checked={checked}\n disabled={disabled}\n aria-label={column.label || column.name}\n onCheckedChange={(value) => onChange(value === true)}\n onClick={(event) => event.stopPropagation()}\n />\n )\n }\n\n return (\n <span className=\"inline-flex items-center gap-2\" onClick={(event) => event.stopPropagation()}>\n <Switch\n checked={checked}\n disabled={disabled}\n aria-label={column.label || column.name}\n onCheckedChange={onChange}\n className={cn(\n toggle.onColor && colorClass(switchOnColorClasses, toggle.onColor),\n toggle.offColor && colorClass(switchOffColorClasses, toggle.offColor),\n )}\n />\n {(checked ? toggle.onIcon : toggle.offIcon) && (\n <Icon\n name={checked ? toggle.onIcon : toggle.offIcon}\n className={cn(\n colorClass(textColorClasses, checked ? toggle.onColor : toggle.offColor, 'gray'),\n )}\n />\n )}\n </span>\n )\n}\n\nfunction flatten(options: OptionOrGroup[]) {\n return options.flatMap((option) => (isOptionGroup(option) ? option.options : [option]))\n}\n\nfunction SelectCell(props: CellProps) {\n const schema = props.column as SelectColumnSchema\n\n return schema.native === false ? (\n <SelectComboboxCell {...props} />\n ) : (\n <NativeSelectCell {...props} />\n )\n}\n\n/**\n * An option label: sanitised HTML under `allowOptionsHtml()`, text otherwise. Long labels\n * wrap unless `wrapOptionLabels(false)` truncates them.\n */\nfunction SelectOptionLabel({\n label,\n html,\n truncate,\n}: {\n label: string\n html?: boolean\n truncate?: boolean\n}) {\n const className = truncate ? 'min-w-0 truncate' : 'min-w-0 break-words whitespace-normal'\n\n // The server sanitises HTML labels (`Support\\Html::sanitize`).\n return html ? (\n <span className={className} dangerouslySetInnerHTML={{ __html: label }} />\n ) : (\n <span className={className}>{label}</span>\n )\n}\n\n/**\n * `SelectColumn::native(false)`: a combobox, searchable with `searchableOptions()`. Options\n * come with the table, or from the server (`optionsSearchPath`) as the user types.\n */\nfunction SelectComboboxCell(props: CellProps) {\n const { column, cell, recordKey, token, component } = props\n const schema = column as SelectColumnSchema\n const t = useT()\n const panel = usePanel()\n const { update, saving, error } = useCellUpdate(props)\n const [value, setValue] = useState(\n cell.state === null || cell.state === undefined ? '' : String(cell.state),\n )\n const [label, setLabel] = useState(cell.optionLabel)\n const [open, setOpen] = useState(false)\n const [search, setSearch] = useState('')\n const [loading, setLoading] = useState(false)\n const [remote, setRemote] = useState<Option[]>([])\n const request = useRef(0)\n const isRemote = Boolean(schema.optionsSearchPath)\n const debounce = schema.optionsSearchDebounce ?? 300\n const staticOptions = flatten(schema.options)\n\n useEffect(() => {\n if (!open || !isRemote || !panel.endpoints.schemaOptions) return\n\n const url = panel.endpoints.schemaOptions\n const timer = setTimeout(() => {\n const current = ++request.current\n setLoading(true)\n\n void searchTableColumnOptions(url, token, component, schema, search)\n .then((results) => current === request.current && setRemote(results))\n .catch(() => current === request.current && setRemote([]))\n .finally(() => current === request.current && setLoading(false))\n }, debounce)\n\n return () => clearTimeout(timer)\n }, [open, search, isRemote, panel.endpoints.schemaOptions, token, component, schema, debounce])\n\n const options = filterSelectColumnOptions(\n isRemote ? remote : staticOptions,\n schema,\n isRemote ? '' : search,\n recordKey,\n )\n const emptyMessage = selectColumnEmptyMessage(schema, {\n loading,\n search,\n optionCount: options.length,\n })\n const currentLabel =\n staticOptions.find((option) => option.value === value)?.label ??\n remote.find((option) => option.value === value)?.label ??\n label\n\n const choose = (next: string, nextLabel?: string) => {\n setValue(next)\n setLabel(nextLabel)\n setOpen(false)\n void update(next === '' ? null : next)\n }\n\n return (\n <span onClick={(event) => event.stopPropagation()}>\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next)\n\n if (!next) setSearch('')\n }}\n >\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n role=\"combobox\"\n aria-expanded={open}\n aria-label={column.label || column.name}\n aria-invalid={error ? true : undefined}\n disabled={Boolean(cell.disabled) || saving}\n className={cn(\n 'h-8 min-w-32 justify-between font-normal',\n error && 'border-destructive',\n )}\n >\n {value !== '' && currentLabel !== undefined ? (\n <SelectOptionLabel label={currentLabel} html={schema.allowOptionsHtml} truncate />\n ) : (\n <span className=\"text-muted-foreground\">\n {schema.placeholder ??\n (value !== '' ? value : t('select_option', {}, 'Select an option'))}\n </span>\n )}\n {loading ? (\n <Spinner className=\"opacity-50\" />\n ) : (\n <ChevronsUpDownIcon className=\"size-4 shrink-0 opacity-50\" />\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-64 p-0\" align=\"start\">\n <Command shouldFilter={false}>\n {schema.searchableOptions && (\n <CommandInput\n placeholder={\n schema.searchPrompt ?? t('form.search_placeholder', {}, 'Type to search…')\n }\n value={search}\n onValueChange={setSearch}\n />\n )}\n <CommandList>\n <CommandEmpty data-slot=\"select-column-message\">\n {emptyMessage.message ?? t(emptyMessage.key, {}, emptyMessage.fallback)}\n </CommandEmpty>\n <CommandGroup>\n {schema.selectablePlaceholder && value !== '' && (\n <CommandItem value=\"\" onSelect={() => choose('')}>\n <span className=\"text-muted-foreground\">\n {schema.placeholder ?? t('clear', {}, 'Clear')}\n </span>\n </CommandItem>\n )}\n {options.map((option) => (\n <CommandItem\n key={option.value}\n value={option.value}\n keywords={[optionText(option.label)]}\n disabled={option.disabled}\n onSelect={() => choose(option.value, option.label)}\n >\n <CheckIcon\n className={cn('size-4', option.value === value ? 'opacity-100' : 'opacity-0')}\n />\n <SelectOptionLabel\n label={option.label}\n html={schema.allowOptionsHtml}\n truncate={schema.wrapOptionLabels === false}\n />\n </CommandItem>\n ))}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n {error && <span className=\"text-destructive block text-xs\">{error}</span>}\n </span>\n )\n}\n\nfunction NativeSelectCell(props: CellProps) {\n const { column, cell } = props\n const schema = column as SelectColumnSchema\n const { update, saving, error } = useCellUpdate(props)\n const [value, setValue] = useState(\n cell.state === null || cell.state === undefined ? '' : String(cell.state),\n )\n\n return (\n <span onClick={(event) => event.stopPropagation()}>\n <select\n value={value}\n disabled={Boolean(cell.disabled) || saving}\n onChange={(event) => {\n setValue(event.target.value)\n void update(event.target.value === '' ? null : event.target.value)\n }}\n aria-invalid={error ? true : undefined}\n className={cn(\n 'border-input dark:bg-input/30 focus-visible:ring-ring/50 h-8 min-w-32 rounded-md border bg-transparent px-2 text-sm shadow-xs outline-none focus-visible:ring-[3px]',\n error && 'border-destructive',\n )}\n >\n {schema.selectablePlaceholder && <option value=\"\">{schema.placeholder ?? ''}</option>}\n {flatten(schema.options)\n .filter((option) => !(schema.ignoreRecord && option.value === String(props.recordKey)))\n .map((option) => (\n <option key={option.value} value={option.value} disabled={option.disabled}>\n {option.label}\n </option>\n ))}\n </select>\n {error && <span className=\"text-destructive block text-xs\">{error}</span>}\n </span>\n )\n}\n\nfunction TextInputCell(props: CellProps) {\n const { column, cell } = props\n const schema = column as TextInputColumnSchema\n const { update, saving, error } = useCellUpdate(props)\n const [value, setValue] = useState(\n cell.state === null || cell.state === undefined ? '' : String(cell.state),\n )\n const initial = cell.state === null || cell.state === undefined ? '' : String(cell.state)\n // `prefix()` / `suffix()`: text affixes around the input, like the TextInput field.\n const grouped = Boolean(cell.prefix || cell.suffix)\n\n const field = (\n <span className={cn('relative block', grouped && 'min-w-0 flex-1')}>\n {schema.prefixIcon && (\n <span\n data-slot=\"input-prefix-icon\"\n aria-hidden=\"true\"\n className={cn(\n 'pointer-events-none absolute start-2.5 top-1/2 flex -translate-y-1/2',\n colorClass(textColorClasses, schema.prefixIconColor, 'gray'),\n )}\n >\n <Icon name={schema.prefixIcon} className=\"size-4\" />\n </span>\n )}\n <Input\n type={schema.inputType}\n value={value}\n placeholder={schema.placeholder}\n step={schema.step}\n inputMode={schema.inputMode as React.HTMLAttributes<HTMLInputElement>['inputMode']}\n disabled={Boolean(cell.disabled) || saving}\n aria-invalid={error ? true : undefined}\n className={cn(\n 'h-8 min-w-32',\n schema.prefixIcon && 'ps-8',\n schema.suffixIcon && 'pe-8',\n grouped &&\n 'h-full rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent',\n )}\n onChange={(event) => setValue(event.target.value)}\n onBlur={() => value !== initial && void update(value)}\n onKeyDown={(event) => event.key === 'Enter' && (event.target as HTMLInputElement).blur()}\n />\n {schema.suffixIcon && (\n <span\n data-slot=\"input-suffix-icon\"\n aria-hidden=\"true\"\n className={cn(\n 'pointer-events-none absolute end-2.5 top-1/2 flex -translate-y-1/2',\n colorClass(textColorClasses, schema.suffixIconColor, 'gray'),\n )}\n >\n <Icon name={schema.suffixIcon} className=\"size-4\" />\n </span>\n )}\n </span>\n )\n\n return (\n <span onClick={(event) => event.stopPropagation()}>\n {grouped ? (\n <span\n data-slot=\"input-group\"\n className={cn(\n 'border-input dark:bg-input/30 has-[input:focus-visible]:border-ring has-[input:focus-visible]:ring-ring/50 flex h-8 min-w-32 items-stretch overflow-hidden rounded-md border shadow-xs has-[input:focus-visible]:ring-[3px]',\n error && 'border-destructive',\n )}\n >\n {cell.prefix && (\n <span\n data-slot=\"input-prefix\"\n className=\"text-muted-foreground bg-muted/50 flex items-center border-e px-2 text-sm\"\n >\n {cell.prefix}\n </span>\n )}\n {field}\n {cell.suffix && (\n <span\n data-slot=\"input-suffix\"\n className=\"text-muted-foreground bg-muted/50 flex items-center border-s px-2 text-sm\"\n >\n {cell.suffix}\n </span>\n )}\n </span>\n ) : (\n field\n )}\n {error && <span className=\"text-destructive block text-xs\">{error}</span>}\n </span>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cells.js","names":[],"sources":["../../../src/components/table/cells.tsx"],"sourcesContent":["import type {\n CellSchema,\n ColorColumnSchema,\n ColumnSchema,\n IconColumnSchema,\n Option,\n OptionOrGroup,\n RecordKey,\n SelectColumnSchema,\n TextInputColumnSchema,\n ToggleColumnSchema,\n ViewColumnSchema,\n} from '@alfakit/core'\nimport {\n columnRegistryKey,\n filterSelectColumnOptions,\n isOptionGroup,\n optionText,\n remainingTextSizeClass,\n resolvePartialProps,\n searchTableColumnOptions,\n selectColumnEmptyMessage,\n stackedImageStyle,\n updateTableCell,\n usesDefaultImageStack,\n} from '@alfakit/core'\nimport { router } from '@inertiajs/react'\nimport { CheckIcon, ChevronsUpDownIcon } from 'lucide-react'\nimport { createElement, useEffect, useId, useRef, useState } from 'react'\nimport { usePanel, useRegistry, useT } from '../../context'\nimport { extraProps } from '../../lib/attributes'\nimport {\n colorClass,\n iconSizeClasses,\n switchOffColorClasses,\n switchOnColorClasses,\n textColorClasses,\n} from '../../lib/colors'\nimport { Icon } from '../../lib/icons'\nimport { cn } from '../../lib/utils'\nimport { FormattedText } from '../entries/text-entry'\nimport { Button } from '../ui/button'\nimport { Checkbox } from '../ui/checkbox'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '../ui/command'\nimport { Input } from '../ui/input'\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover'\nimport { Spinner } from '../ui/spinner'\nimport { Switch } from '../ui/switch'\n\nexport interface CellProps {\n column: ColumnSchema\n cell: CellSchema\n recordKey: RecordKey\n token: string\n component: string\n}\n\nexport function TableCellContent(props: CellProps) {\n const { column } = props\n // A component registered as `column:<type>` replaces the built-in cell renderer.\n const Custom = useRegistry().resolve(columnRegistryKey(column))\n\n if (Custom) {\n return createElement(Custom, props)\n }\n\n switch (column.type) {\n case 'IconColumn':\n return <IconCell {...props} />\n case 'ImageColumn':\n return <ImageCell {...props} />\n case 'ColorColumn':\n return <ColorCell {...props} />\n case 'ToggleColumn':\n case 'CheckboxColumn':\n return <BooleanCell {...props} />\n case 'SelectColumn':\n return <SelectCell {...props} />\n case 'TextInputColumn':\n return <TextInputCell {...props} />\n case 'ViewColumn':\n return <ViewCell {...props} />\n default:\n return <TextCell {...props} />\n }\n}\n\n/** `IconColumn`: one icon, or one per item of a list state (`wrap()` lets them wrap). */\nfunction IconCell({ column, cell }: CellProps) {\n const icons = cell.icons ?? (cell.icon ? [{ icon: cell.icon, color: cell.color }] : [])\n const sizeClass = colorClass(iconSizeClasses, cell.size, 'md')\n\n if (icons.length === 0) {\n return <span className=\"text-muted-foreground\">—</span>\n }\n\n if (!cell.icons) {\n return (\n <Icon\n name={icons[0]!.icon}\n className={cn(sizeClass, icons[0]!.color && textColorClasses[icons[0]!.color])}\n />\n )\n }\n\n return (\n <div\n data-slot=\"icon-column-icons\"\n className={cn(\n 'flex items-center gap-1.5',\n (column as IconColumnSchema).wrap ? 'flex-wrap' : 'flex-nowrap',\n )}\n >\n {icons.map((item, index) => (\n <Icon\n key={index}\n name={item.icon}\n className={cn(sizeClass, item.color && textColorClasses[item.color])}\n />\n ))}\n </div>\n )\n}\n\n/** `ViewColumn`: the application component registered under the column's `view()` name. */\nfunction ViewCell(props: CellProps) {\n const t = useT()\n const name = (props.column as ViewColumnSchema).component ?? ''\n const Custom = useRegistry().resolve(name)\n\n if (!name || !Custom) {\n return (\n <span className=\"text-destructive text-xs\">\n {t('component_not_registered', { component: name }, `Component ${name} is not registered.`)}\n </span>\n )\n }\n\n return createElement(Custom, { ...(props.cell.props ?? {}), state: props.cell.state, ...props })\n}\n\nfunction TextCell({ column, cell }: CellProps) {\n const text = (\n <FormattedText\n value={cell.state}\n schema={{\n ...(column as object),\n color: cell.color,\n icon: cell.icon,\n iconPosition: cell.iconPosition,\n iconColor: cell.iconColor,\n itemColors: cell.itemColors,\n itemIcons: cell.itemIcons,\n itemUrls: cell.itemUrls,\n }}\n />\n )\n const description = cell.description ? (\n <span className=\"text-muted-foreground block text-xs\">{cell.description}</span>\n ) : null\n const position =\n (column as { descriptionPosition?: 'above' | 'below' }).descriptionPosition ?? 'below'\n\n return (\n <div className=\"flex flex-col gap-0.5\">\n {position === 'above' && description}\n {text}\n {position === 'below' && description}\n </div>\n )\n}\n\nfunction ImageCell({ column, cell }: CellProps) {\n const urls = Array.isArray(cell.state) ? (cell.state as string[]) : []\n const schema = column as {\n circular?: boolean\n square?: boolean\n size?: number | string\n height?: number | string\n width?: string\n stacked?: boolean\n limit?: number\n limitedRemainingText?: boolean\n limitedRemainingTextSize?: string\n wrap?: boolean\n ring?: number\n overlap?: number\n }\n const limit = schema.limit ?? urls.length\n const size = schema.size ?? 40\n\n if (urls.length === 0) {\n return <span className=\"text-muted-foreground\">—</span>\n }\n\n return (\n <div\n className={cn(\n 'flex items-center',\n schema.wrap && 'flex-wrap',\n schema.stacked ? usesDefaultImageStack(schema) && '-space-x-2' : 'gap-1.5',\n schema.wrap && schema.stacked && 'gap-y-1.5',\n )}\n >\n {urls.slice(0, limit).map((url, index) => (\n <img\n key={index}\n src={url}\n alt={cell.alt ?? ''}\n style={{\n height: schema.height ?? size,\n width: schema.width ?? (schema.square || schema.circular ? size : undefined),\n ...stackedImageStyle(index, schema),\n }}\n {...extraProps(\n cell.extraImgAttributes,\n cn(\n 'object-cover',\n schema.circular ? 'rounded-full' : 'rounded-md',\n schema.stacked && usesDefaultImageStack(schema) && 'ring-background ring-2',\n ),\n )}\n />\n ))}\n {schema.limitedRemainingText && urls.length > limit && (\n <span\n data-slot=\"image-remaining\"\n className={cn(\n 'text-muted-foreground ms-1',\n remainingTextSizeClass(schema.limitedRemainingTextSize),\n )}\n >\n +{urls.length - limit}\n </span>\n )}\n </div>\n )\n}\n\nfunction ColorCell({ column, cell }: CellProps) {\n const t = useT()\n const schema = column as ColorColumnSchema\n const [copied, setCopied] = useState<string | null>(null)\n const colors = Array.isArray(cell.state)\n ? (cell.state as string[])\n : cell.state\n ? [String(cell.state)]\n : []\n\n if (colors.length === 0) {\n return <span className=\"text-muted-foreground\">—</span>\n }\n\n const copy = (color: string) => {\n void navigator.clipboard?.writeText(color).then(() => {\n setCopied(color)\n setTimeout(() => setCopied(null), schema.copyMessageDuration ?? 1500)\n })\n }\n\n return (\n <div className={cn('flex items-center gap-1.5', schema.wrap ? 'flex-wrap' : 'flex-nowrap')}>\n {colors.map((color) =>\n schema.copyable ? (\n <button\n key={color}\n type=\"button\"\n data-slot=\"color-copy\"\n title={color}\n aria-label={`${t('copy', {}, 'Copy')} ${color}`}\n className=\"focus-visible:ring-ring/50 inline-flex rounded outline-none focus-visible:ring-[3px]\"\n onClick={(event) => {\n // The cell may sit inside a link or a clickable row.\n event.preventDefault()\n event.stopPropagation()\n copy(color)\n }}\n >\n <span\n className=\"inline-flex size-5 items-center justify-center rounded border shadow-xs\"\n style={{ backgroundColor: color }}\n >\n {copied === color && <CheckIcon className=\"size-3 text-white mix-blend-difference\" />}\n </span>\n </button>\n ) : (\n <span\n key={color}\n title={color}\n className=\"size-5 rounded border shadow-xs\"\n style={{ backgroundColor: color }}\n />\n ),\n )}\n {schema.copyable && copied && (\n <span role=\"status\" className={cn('text-xs', !schema.copyMessage && 'sr-only')}>\n {schema.copyMessage ?? t('copied', {}, 'Copied')}\n </span>\n )}\n </div>\n )\n}\n\nfunction useCellUpdate({ recordKey, column, token, component }: CellProps) {\n const panel = usePanel()\n const [saving, setSaving] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const update = async (state: unknown) => {\n if (!panel.endpoints.tableCell || !panel.endpoints.tableReorder) return\n\n setSaving(true)\n setError(null)\n\n try {\n await updateTableCell(\n { cell: panel.endpoints.tableCell, reorder: panel.endpoints.tableReorder },\n token,\n component,\n recordKey,\n column.name,\n state,\n )\n router.reload({ only: resolvePartialProps(['page']) })\n } catch (caught) {\n const errors = (caught as { errors?: Record<string, string[]> }).errors\n setError(errors?.state?.[0] ?? (caught as Error).message)\n } finally {\n setSaving(false)\n }\n }\n\n return { update, saving, error }\n}\n\nfunction BooleanCell(props: CellProps) {\n const { column, cell } = props\n const { update, saving } = useCellUpdate(props)\n const [checked, setChecked] = useState(Boolean(cell.state))\n const disabled = Boolean(cell.disabled) || saving\n const toggle = column as ToggleColumnSchema\n\n const onChange = (next: boolean) => {\n setChecked(next)\n void update(next)\n }\n\n if (column.type === 'CheckboxColumn') {\n return (\n <Checkbox\n checked={checked}\n disabled={disabled}\n aria-label={column.label || column.name}\n onCheckedChange={(value) => onChange(value === true)}\n onClick={(event) => event.stopPropagation()}\n />\n )\n }\n\n return (\n <span className=\"inline-flex items-center gap-2\" onClick={(event) => event.stopPropagation()}>\n <Switch\n checked={checked}\n disabled={disabled}\n aria-label={column.label || column.name}\n onCheckedChange={onChange}\n className={cn(\n toggle.onColor && colorClass(switchOnColorClasses, toggle.onColor),\n toggle.offColor && colorClass(switchOffColorClasses, toggle.offColor),\n )}\n />\n {(checked ? toggle.onIcon : toggle.offIcon) && (\n <Icon\n name={checked ? toggle.onIcon : toggle.offIcon}\n className={cn(\n colorClass(textColorClasses, checked ? toggle.onColor : toggle.offColor, 'gray'),\n )}\n />\n )}\n </span>\n )\n}\n\nfunction flatten(options: OptionOrGroup[]) {\n return options.flatMap((option) => (isOptionGroup(option) ? option.options : [option]))\n}\n\nfunction SelectCell(props: CellProps) {\n const schema = props.column as SelectColumnSchema\n\n return schema.native === false ? (\n <SelectComboboxCell {...props} />\n ) : (\n <NativeSelectCell {...props} />\n )\n}\n\n/**\n * An option label: sanitised HTML under `allowOptionsHtml()`, text otherwise. Long labels\n * wrap unless `wrapOptionLabels(false)` truncates them.\n */\nfunction SelectOptionLabel({\n label,\n html,\n truncate,\n}: {\n label: string\n html?: boolean\n truncate?: boolean\n}) {\n const className = truncate ? 'min-w-0 truncate' : 'min-w-0 break-words whitespace-normal'\n\n // The server sanitises HTML labels (`Support\\Html::sanitize`).\n return html ? (\n <span className={className} dangerouslySetInnerHTML={{ __html: label }} />\n ) : (\n <span className={className}>{label}</span>\n )\n}\n\n/**\n * `SelectColumn::native(false)`: a combobox, searchable with `searchableOptions()`. Options\n * come with the table, or from the server (`optionsSearchPath`) as the user types.\n */\nfunction SelectComboboxCell(props: CellProps) {\n const { column, cell, recordKey, token, component } = props\n const schema = column as SelectColumnSchema\n const t = useT()\n const panel = usePanel()\n const { update, saving, error } = useCellUpdate(props)\n const [value, setValue] = useState(\n cell.state === null || cell.state === undefined ? '' : String(cell.state),\n )\n const [label, setLabel] = useState(cell.optionLabel)\n const [open, setOpen] = useState(false)\n const [search, setSearch] = useState('')\n const [loading, setLoading] = useState(false)\n const [remote, setRemote] = useState<Option[]>([])\n const request = useRef(0)\n const isRemote = Boolean(schema.optionsSearchPath)\n const debounce = schema.optionsSearchDebounce ?? 300\n const staticOptions = flatten(schema.options)\n\n useEffect(() => {\n if (!open || !isRemote || !panel.endpoints.schemaOptions) return\n\n const url = panel.endpoints.schemaOptions\n const timer = setTimeout(() => {\n const current = ++request.current\n setLoading(true)\n\n void searchTableColumnOptions(url, token, component, schema, search)\n .then((results) => current === request.current && setRemote(results))\n .catch(() => current === request.current && setRemote([]))\n .finally(() => current === request.current && setLoading(false))\n }, debounce)\n\n return () => clearTimeout(timer)\n }, [open, search, isRemote, panel.endpoints.schemaOptions, token, component, schema, debounce])\n\n const options = filterSelectColumnOptions(\n isRemote ? remote : staticOptions,\n schema,\n isRemote ? '' : search,\n recordKey,\n )\n const emptyMessage = selectColumnEmptyMessage(schema, {\n loading,\n search,\n optionCount: options.length,\n })\n const currentLabel =\n staticOptions.find((option) => option.value === value)?.label ??\n remote.find((option) => option.value === value)?.label ??\n label\n\n const choose = (next: string, nextLabel?: string) => {\n setValue(next)\n setLabel(nextLabel)\n setOpen(false)\n void update(next === '' ? null : next)\n }\n\n return (\n <span onClick={(event) => event.stopPropagation()}>\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next)\n\n if (!next) setSearch('')\n }}\n >\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n role=\"combobox\"\n aria-expanded={open}\n aria-label={column.label || column.name}\n aria-invalid={error ? true : undefined}\n disabled={Boolean(cell.disabled) || saving}\n className={cn(\n 'h-8 min-w-32 justify-between font-normal',\n error && 'border-destructive',\n )}\n >\n {value !== '' && currentLabel !== undefined ? (\n <SelectOptionLabel label={currentLabel} html={schema.allowOptionsHtml} truncate />\n ) : (\n <span className=\"text-muted-foreground\">\n {schema.placeholder ??\n (value !== '' ? value : t('select_option', {}, 'Select an option'))}\n </span>\n )}\n {loading ? (\n <Spinner className=\"opacity-50\" />\n ) : (\n <ChevronsUpDownIcon className=\"size-4 shrink-0 opacity-50\" />\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-64 p-0\" align=\"start\">\n <Command shouldFilter={false}>\n {schema.searchableOptions && (\n <CommandInput\n placeholder={\n schema.searchPrompt ?? t('form.search_placeholder', {}, 'Type to search…')\n }\n value={search}\n onValueChange={setSearch}\n />\n )}\n <CommandList>\n <CommandEmpty data-slot=\"select-column-message\">\n {emptyMessage.message ?? t(emptyMessage.key, {}, emptyMessage.fallback)}\n </CommandEmpty>\n <CommandGroup>\n {schema.selectablePlaceholder && value !== '' && (\n <CommandItem value=\"\" onSelect={() => choose('')}>\n <span className=\"text-muted-foreground\">\n {schema.placeholder ?? t('clear', {}, 'Clear')}\n </span>\n </CommandItem>\n )}\n {options.map((option) => (\n <CommandItem\n key={option.value}\n value={option.value}\n keywords={[optionText(option.label)]}\n disabled={option.disabled}\n onSelect={() => choose(option.value, option.label)}\n >\n <CheckIcon\n className={cn('size-4', option.value === value ? 'opacity-100' : 'opacity-0')}\n />\n <SelectOptionLabel\n label={option.label}\n html={schema.allowOptionsHtml}\n truncate={schema.wrapOptionLabels === false}\n />\n </CommandItem>\n ))}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n {error && <span className=\"text-destructive block text-xs\">{error}</span>}\n </span>\n )\n}\n\nfunction NativeSelectCell(props: CellProps) {\n const { column, cell } = props\n const schema = column as SelectColumnSchema\n const { update, saving, error } = useCellUpdate(props)\n const [value, setValue] = useState(\n cell.state === null || cell.state === undefined ? '' : String(cell.state),\n )\n\n const errorId = useId()\n\n return (\n <span onClick={(event) => event.stopPropagation()}>\n <select\n value={value}\n disabled={Boolean(cell.disabled) || saving}\n onChange={(event) => {\n setValue(event.target.value)\n void update(event.target.value === '' ? null : event.target.value)\n }}\n aria-label={column.label || column.name}\n aria-invalid={error ? true : undefined}\n aria-describedby={error ? errorId : undefined}\n className={cn(\n 'border-input dark:bg-input/30 focus-visible:ring-ring/50 h-8 min-w-32 rounded-md border bg-transparent px-2 text-sm shadow-xs outline-none focus-visible:ring-[3px]',\n error && 'border-destructive',\n )}\n >\n {schema.selectablePlaceholder && <option value=\"\">{schema.placeholder ?? ''}</option>}\n {flatten(schema.options)\n .filter((option) => !(schema.ignoreRecord && option.value === String(props.recordKey)))\n .map((option) => (\n <option key={option.value} value={option.value} disabled={option.disabled}>\n {option.label}\n </option>\n ))}\n </select>\n {error && (\n <span id={errorId} className=\"text-destructive block text-xs\">\n {error}\n </span>\n )}\n </span>\n )\n}\n\nfunction TextInputCell(props: CellProps) {\n const { column, cell } = props\n const schema = column as TextInputColumnSchema\n const { update, saving, error } = useCellUpdate(props)\n const [value, setValue] = useState(\n cell.state === null || cell.state === undefined ? '' : String(cell.state),\n )\n const initial = cell.state === null || cell.state === undefined ? '' : String(cell.state)\n // `prefix()` / `suffix()`: text affixes around the input, like the TextInput field.\n const grouped = Boolean(cell.prefix || cell.suffix)\n const errorId = useId()\n\n const field = (\n <span className={cn('relative block', grouped && 'min-w-0 flex-1')}>\n {schema.prefixIcon && (\n <span\n data-slot=\"input-prefix-icon\"\n aria-hidden=\"true\"\n className={cn(\n 'pointer-events-none absolute start-2.5 top-1/2 flex -translate-y-1/2',\n colorClass(textColorClasses, schema.prefixIconColor, 'gray'),\n )}\n >\n <Icon name={schema.prefixIcon} className=\"size-4\" />\n </span>\n )}\n <Input\n type={schema.inputType}\n value={value}\n placeholder={schema.placeholder}\n step={schema.step}\n inputMode={schema.inputMode as React.HTMLAttributes<HTMLInputElement>['inputMode']}\n disabled={Boolean(cell.disabled) || saving}\n aria-label={column.label || column.name}\n aria-invalid={error ? true : undefined}\n aria-describedby={error ? errorId : undefined}\n className={cn(\n 'h-8 min-w-32',\n schema.prefixIcon && 'ps-8',\n schema.suffixIcon && 'pe-8',\n grouped &&\n 'h-full rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent',\n )}\n onChange={(event) => setValue(event.target.value)}\n onBlur={() => value !== initial && void update(value)}\n onKeyDown={(event) => event.key === 'Enter' && (event.target as HTMLInputElement).blur()}\n />\n {schema.suffixIcon && (\n <span\n data-slot=\"input-suffix-icon\"\n aria-hidden=\"true\"\n className={cn(\n 'pointer-events-none absolute end-2.5 top-1/2 flex -translate-y-1/2',\n colorClass(textColorClasses, schema.suffixIconColor, 'gray'),\n )}\n >\n <Icon name={schema.suffixIcon} className=\"size-4\" />\n </span>\n )}\n </span>\n )\n\n return (\n <span onClick={(event) => event.stopPropagation()}>\n {grouped ? (\n <span\n data-slot=\"input-group\"\n className={cn(\n 'border-input dark:bg-input/30 has-[input:focus-visible]:border-ring has-[input:focus-visible]:ring-ring/50 flex h-8 min-w-32 items-stretch overflow-hidden rounded-md border shadow-xs has-[input:focus-visible]:ring-[3px]',\n error && 'border-destructive',\n )}\n >\n {cell.prefix && (\n <span\n data-slot=\"input-prefix\"\n className=\"text-muted-foreground bg-muted/50 flex items-center border-e px-2 text-sm\"\n >\n {cell.prefix}\n </span>\n )}\n {field}\n {cell.suffix && (\n <span\n data-slot=\"input-suffix\"\n className=\"text-muted-foreground bg-muted/50 flex items-center border-s px-2 text-sm\"\n >\n {cell.suffix}\n </span>\n )}\n </span>\n ) : (\n field\n )}\n {error && (\n <span id={errorId} className=\"text-destructive block text-xs\">\n {error}\n </span>\n )}\n </span>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useT } from "../../context.js";
|
|
2
2
|
import { cn } from "../../lib/utils.js";
|
|
3
|
+
import { colorClass, textColorClasses } from "../../lib/colors.js";
|
|
3
4
|
import { Icon } from "../../lib/icons.js";
|
|
4
5
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger } from "../ui/dropdown-menu.js";
|
|
5
6
|
import { Checkbox } from "../ui/checkbox.js";
|
|
@@ -122,7 +123,7 @@ function TableGroupingDropdown({ table, groups, trigger, active, onGroup, onDire
|
|
|
122
123
|
/** A group heading row (`data-slot="table-group"`), with a collapse toggle when collapsible. */
|
|
123
124
|
function GroupHeaderRow({ group, collapsed, collapsible, colSpan, onToggle, selection }) {
|
|
124
125
|
const t = useT();
|
|
125
|
-
const
|
|
126
|
+
const text = /* @__PURE__ */ jsxs("span", {
|
|
126
127
|
className: "flex flex-col items-start",
|
|
127
128
|
children: [/* @__PURE__ */ jsx("span", {
|
|
128
129
|
className: "font-medium",
|
|
@@ -132,6 +133,15 @@ function GroupHeaderRow({ group, collapsed, collapsible, colSpan, onToggle, sele
|
|
|
132
133
|
children: group.description
|
|
133
134
|
})]
|
|
134
135
|
});
|
|
136
|
+
const content = group.icon ? /* @__PURE__ */ jsxs("span", {
|
|
137
|
+
"data-slot": "table-group-title",
|
|
138
|
+
className: "flex items-center gap-2",
|
|
139
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
140
|
+
name: group.icon,
|
|
141
|
+
className: cn("size-4 shrink-0", colorClass(textColorClasses, group.color, "gray")),
|
|
142
|
+
"aria-hidden": "true"
|
|
143
|
+
}), text]
|
|
144
|
+
}) : text;
|
|
135
145
|
return /* @__PURE__ */ jsx(TableRow, {
|
|
136
146
|
"data-slot": "table-group",
|
|
137
147
|
className: "bg-muted/50 hover:bg-muted/50",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grouping.js","names":[],"sources":["../../../src/components/table/grouping.tsx"],"sourcesContent":["import type {\n ColumnSchema,\n TableRecordGroupSchema,\n TableSchema,\n TriggerButtonView,\n} from '@alfakit/core'\nimport {\n initialCollapsedGroups,\n registerTablePersistence,\n toggleCollapsedGroup,\n triggerButtonView,\n visitTable,\n} from '@alfakit/core'\nimport { ChevronDownIcon, ChevronRightIcon, LayersIcon } from 'lucide-react'\nimport { useEffect, useState } from 'react'\nimport { useT } from '../../context'\nimport { Icon } from '../../lib/icons'\nimport { cn } from '../../lib/utils'\nimport { Checkbox } from '../ui/checkbox'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu'\nimport { TableCell, TableRow } from '../ui/table'\nimport { TableTriggerButton } from './trigger-button'\n\n/** The \"group by\" menu: one of the table's groups (or none) and the direction. */\nexport function TableGroupingMenu({ table }: { table: TableSchema }) {\n const t = useT()\n\n if (!table.groups || table.groups.length === 0) {\n return null\n }\n\n const active = table.grouping?.group ?? ''\n const groups = table.groups\n // `groupRecordsTriggerAction()`.\n const trigger = triggerButtonView(table, 'groupRecords', {\n label: t('table_grouping.group_by', {}, 'Group by'),\n })\n const changeGroup = (group: string) => visitTable(table.identifier, { group }, ['page'])\n const changeDirection = (direction: string) =>\n visitTable(table.identifier, { groupDirection: direction === 'desc' ? 'desc' : 'asc' }, [\n 'page',\n ])\n const inDropdownOnly = Boolean(table.groupingSettingsInDropdownOnDesktop)\n\n // Desktop default: the settings inline in the toolbar (the dropdown is for phones).\n const inline = inDropdownOnly ? null : (\n <div data-slot=\"table-grouping-inline\" className=\"hidden items-center gap-2 text-sm sm:flex\">\n <label className=\"flex items-center gap-2\">\n <span className=\"text-muted-foreground\">\n {t('table_grouping.group_by', {}, 'Group by')}\n </span>\n <select\n value={active}\n onChange={(event) => changeGroup(event.target.value)}\n className=\"border-input h-8 rounded-md border bg-transparent px-2 text-sm\"\n >\n <option value=\"\">{t('table_grouping.none', {}, 'No grouping')}</option>\n {groups.map((group) => (\n <option key={group.id} value={group.id}>\n {group.label}\n </option>\n ))}\n </select>\n </label>\n {table.grouping && !table.groupingDirectionSettingHidden && (\n <label className=\"flex items-center\">\n <span className=\"sr-only\">{t('table_grouping.direction', {}, 'Group direction')}</span>\n <select\n value={table.grouping.direction}\n onChange={(event) => changeDirection(event.target.value)}\n className=\"border-input h-8 rounded-md border bg-transparent px-2 text-sm\"\n >\n <option value=\"asc\">{t('table_grouping.ascending', {}, 'Ascending')}</option>\n <option value=\"desc\">{t('table_grouping.descending', {}, 'Descending')}</option>\n </select>\n </label>\n )}\n </div>\n )\n\n if (!trigger) return inline\n\n return (\n <>\n {inline}\n <div className={cn(!inDropdownOnly && 'sm:hidden')}>\n <TableGroupingDropdown\n table={table}\n groups={groups}\n trigger={trigger}\n active={active}\n onGroup={changeGroup}\n onDirection={changeDirection}\n />\n </div>\n </>\n )\n}\n\nfunction TableGroupingDropdown({\n table,\n groups,\n trigger,\n active,\n onGroup,\n onDirection,\n}: {\n table: TableSchema\n groups: NonNullable<TableSchema['groups']>\n trigger: TriggerButtonView\n active: string\n onGroup: (group: string) => void\n onDirection: (direction: string) => void\n}) {\n const t = useT()\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <TableTriggerButton\n view={trigger}\n defaultIcon={<Icon name=\"alfakit::tables.actions.group\" fallback={LayersIcon} />}\n responsiveLabel={!table.triggerActions?.groupRecords}\n active={Boolean(table.grouping)}\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"min-w-48\">\n <DropdownMenuLabel>{t('table_grouping.group_by', {}, 'Group by')}</DropdownMenuLabel>\n <DropdownMenuRadioGroup value={active} onValueChange={onGroup}>\n <DropdownMenuRadioItem value=\"\">\n {t('table_grouping.none', {}, 'No grouping')}\n </DropdownMenuRadioItem>\n {groups.map((group) => (\n <DropdownMenuRadioItem key={group.id} value={group.id}>\n {group.label}\n </DropdownMenuRadioItem>\n ))}\n </DropdownMenuRadioGroup>\n {table.grouping && !table.groupingDirectionSettingHidden && (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuLabel>\n {t('table_grouping.direction', {}, 'Group direction')}\n </DropdownMenuLabel>\n <DropdownMenuRadioGroup value={table.grouping.direction} onValueChange={onDirection}>\n <DropdownMenuRadioItem value=\"asc\">\n {t('table_grouping.ascending', {}, 'Ascending')}\n </DropdownMenuRadioItem>\n <DropdownMenuRadioItem value=\"desc\">\n {t('table_grouping.descending', {}, 'Descending')}\n </DropdownMenuRadioItem>\n </DropdownMenuRadioGroup>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\n\n/** A group heading row (`data-slot=\"table-group\"`), with a collapse toggle when collapsible. */\nexport function GroupHeaderRow({\n group,\n collapsed,\n collapsible,\n colSpan,\n onToggle,\n selection,\n}: {\n group: TableRecordGroupSchema\n collapsed: boolean\n collapsible: boolean\n colSpan: number\n onToggle: () => void\n /** `selectGroupsOnly()`: a checkbox selecting the group's records on the page. */\n selection?: { checked: boolean | 'indeterminate'; onChange: (checked: boolean) => void }\n}) {\n const t = useT()\n const content = (\n <span className=\"flex flex-col items-start\">\n <span className=\"font-medium\">{group.title}</span>\n {group.description && (\n <span className=\"text-muted-foreground text-xs font-normal\">{group.description}</span>\n )}\n </span>\n )\n\n return (\n <TableRow data-slot=\"table-group\" className=\"bg-muted/50 hover:bg-muted/50\">\n <TableCell colSpan={colSpan} className=\"py-2\">\n <span className=\"flex items-center gap-3\">\n {selection && (\n <Checkbox\n checked={selection.checked}\n onCheckedChange={(checked) => selection.onChange(checked === true)}\n aria-label={t('table.select_group', { group: group.title }, 'Select group :group')}\n />\n )}\n {collapsible ? (\n <button\n type=\"button\"\n className=\"focus-visible:ring-ring/50 flex items-center gap-2 rounded-sm text-start outline-none focus-visible:ring-[3px]\"\n aria-expanded={!collapsed}\n aria-label={`${collapsed ? t('table_grouping.expand', {}, 'Expand group') : t('table_grouping.collapse', {}, 'Collapse group')}: ${group.title}`}\n onClick={onToggle}\n >\n {collapsed ? (\n <ChevronRightIcon className=\"size-4 shrink-0 rtl:rotate-180\" aria-hidden=\"true\" />\n ) : (\n <Icon\n name=\"alfakit::tables.grouping.collapse-button\"\n fallback={ChevronDownIcon}\n className=\"size-4 shrink-0\"\n aria-hidden=\"true\"\n />\n )}\n {content}\n </button>\n ) : (\n content\n )}\n </span>\n </TableCell>\n </TableRow>\n )\n}\n\n/**\n * Collapsed group keys. Starts collapsed for `collapsedGroupsByDefault()` and resets when\n * the table is grouped differently.\n */\nexport function useCollapsedGroups(\n table: Pick<TableSchema, 'grouping' | 'recordGroups'>,\n): [Set<string>, (key: string) => void] {\n const groupId = table.grouping ? `${table.grouping.group}:${table.grouping.direction}` : ''\n const [state, setState] = useState(() => ({\n groupId,\n collapsed: initialCollapsedGroups(table),\n }))\n\n if (state.groupId !== groupId) {\n setState({ groupId, collapsed: initialCollapsedGroups(table) })\n }\n\n return [\n state.collapsed,\n (key: string) =>\n setState((current) => ({\n ...current,\n collapsed: toggleCollapsedGroup(current.collapsed, key),\n })),\n ]\n}\n\n/** Register the table's session-persisted keys so cleared values are sent explicitly. */\nexport function useTablePersistence(table: Pick<TableSchema, 'identifier' | 'persistedState'>) {\n const keys = (table.persistedState ?? []).join(',')\n\n useEffect(\n () => registerTablePersistence(table.identifier, keys ? keys.split(',') : undefined),\n [table.identifier, keys],\n )\n}\n\n/** Number of cells in a row of `columns` plus leading and trailing cells. */\nexport function rowCellCount(columns: ColumnSchema[], leading: number, trailing: number): number {\n return columns.length + leading + trailing\n}\n"],"mappings":";;;;;;;;;;;;;AAgCA,SAAgB,kBAAkB,EAAE,SAAiC;CACnE,MAAM,IAAI,KAAK;CAEf,IAAI,CAAC,MAAM,UAAU,MAAM,OAAO,WAAW,GAC3C,OAAO;CAGT,MAAM,SAAS,MAAM,UAAU,SAAS;CACxC,MAAM,SAAS,MAAM;CAErB,MAAM,UAAU,kBAAkB,OAAO,gBAAgB,EACvD,OAAO,EAAE,2BAA2B,CAAC,GAAG,UAAU,EACpD,CAAC;CACD,MAAM,eAAe,UAAkB,WAAW,MAAM,YAAY,EAAE,MAAM,GAAG,CAAC,MAAM,CAAC;CACvF,MAAM,mBAAmB,cACvB,WAAW,MAAM,YAAY,EAAE,gBAAgB,cAAc,SAAS,SAAS,MAAM,GAAG,CACtF,MACF,CAAC;CACH,MAAM,iBAAiB,QAAQ,MAAM,mCAAmC;CAGxE,MAAM,SAAS,iBAAiB,OAC9B,qBAAC,OAAD;EAAK,aAAU;EAAwB,WAAU;EAAjD,UAAA,CACE,qBAAC,SAAD;GAAO,WAAU;GAAjB,UAAA,CACE,oBAAC,QAAD;IAAM,WAAU;IACb,UAAA,EAAE,2BAA2B,CAAC,GAAG,UAAU;GACxC,CAAA,GACN,qBAAC,UAAD;IACE,OAAO;IACP,WAAW,UAAU,YAAY,MAAM,OAAO,KAAK;IACnD,WAAU;IAHZ,UAAA,CAKE,oBAAC,UAAD;KAAQ,OAAM;KAAI,UAAA,EAAE,uBAAuB,CAAC,GAAG,aAAa;IAAU,CAAA,GACrE,OAAO,KAAK,UACX,oBAAC,UAAD;KAAuB,OAAO,MAAM;KACjC,UAAA,MAAM;IACD,GAFK,MAAM,EAEX,CACT,CACK;GACH,CAAA,CAAA;EACN,CAAA,GAAA,MAAM,YAAY,CAAC,MAAM,kCACxB,qBAAC,SAAD;GAAO,WAAU;GAAjB,UAAA,CACE,oBAAC,QAAD;IAAM,WAAU;IAAW,UAAA,EAAE,4BAA4B,CAAC,GAAG,iBAAiB;GAAQ,CAAA,GACtF,qBAAC,UAAD;IACE,OAAO,MAAM,SAAS;IACtB,WAAW,UAAU,gBAAgB,MAAM,OAAO,KAAK;IACvD,WAAU;IAHZ,UAAA,CAKE,oBAAC,UAAD;KAAQ,OAAM;KAAO,UAAA,EAAE,4BAA4B,CAAC,GAAG,WAAW;IAAU,CAAA,GAC5E,oBAAC,UAAD;KAAQ,OAAM;KAAQ,UAAA,EAAE,6BAA6B,CAAC,GAAG,YAAY;IAAU,CAAA,CACzE;GACH,CAAA,CAAA;EAEN,CAAA,CAAA;;CAGP,IAAI,CAAC,SAAS,OAAO;CAErB,OACE,qBAAA,YAAA,EAAA,UAAA,CACG,QACD,oBAAC,OAAD;EAAK,WAAW,GAAG,CAAC,kBAAkB,WAAW;EAC/C,UAAA,oBAAC,uBAAD;GACS;GACC;GACC;GACD;GACR,SAAS;GACT,aAAa;EACd,CAAA;CACE,CAAA,CACL,EAAA,CAAA;AAEN;AAEA,SAAS,sBAAsB,EAC7B,OACA,QACA,SACA,QACA,SACA,eAQC;CACD,MAAM,IAAI,KAAK;CAEf,OACE,qBAAC,cAAD,EAAA,UAAA,CACE,oBAAC,qBAAD;EAAqB,SAAA;EACnB,UAAA,oBAAC,oBAAD;GACE,MAAM;GACN,aAAa,oBAAC,MAAD;IAAM,MAAK;IAAgC,UAAU;GAAa,CAAA;GAC/E,iBAAiB,CAAC,MAAM,gBAAgB;GACxC,QAAQ,QAAQ,MAAM,QAAQ;EAC/B,CAAA;CACkB,CAAA,GACrB,qBAAC,qBAAD;EAAqB,OAAM;EAAM,WAAU;EAA3C,UAAA;GACE,oBAAC,mBAAD,EAAA,UAAoB,EAAE,2BAA2B,CAAC,GAAG,UAAU,EAAqB,CAAA;GACpF,qBAAC,wBAAD;IAAwB,OAAO;IAAQ,eAAe;IAAtD,UAAA,CACE,oBAAC,uBAAD;KAAuB,OAAM;KAC1B,UAAA,EAAE,uBAAuB,CAAC,GAAG,aAAa;IACtB,CAAA,GACtB,OAAO,KAAK,UACX,oBAAC,uBAAD;KAAsC,OAAO,MAAM;KAChD,UAAA,MAAM;IACc,GAFK,MAAM,EAEX,CACxB,CACqB;;GACvB,MAAM,YAAY,CAAC,MAAM,kCACxB,qBAAA,YAAA,EAAA,UAAA;IACE,oBAAC,uBAAD,CAAwB,CAAA;IACxB,oBAAC,mBAAD,EAAA,UACG,EAAE,4BAA4B,CAAC,GAAG,iBAAiB,EACnC,CAAA;IACnB,qBAAC,wBAAD;KAAwB,OAAO,MAAM,SAAS;KAAW,eAAe;KAAxE,UAAA,CACE,oBAAC,uBAAD;MAAuB,OAAM;MAC1B,UAAA,EAAE,4BAA4B,CAAC,GAAG,WAAW;KACzB,CAAA,GACvB,oBAAC,uBAAD;MAAuB,OAAM;MAC1B,UAAA,EAAE,6BAA6B,CAAC,GAAG,YAAY;KAC3B,CAAA,CACD;;GACxB,EAAA,CAAA;EAEe;CACT,CAAA,CAAA,EAAA,CAAA;AAElB;;AAGA,SAAgB,eAAe,EAC7B,OACA,WACA,aACA,SACA,UACA,aASC;CACD,MAAM,IAAI,KAAK;CACf,MAAM,UACJ,qBAAC,QAAD;EAAM,WAAU;EAAhB,UAAA,CACE,oBAAC,QAAD;GAAM,WAAU;GAAe,UAAA,MAAM;EAAY,CAAA,GAChD,MAAM,eACL,oBAAC,QAAD;GAAM,WAAU;GAA6C,UAAA,MAAM;EAAkB,CAAA,CAEnF;;CAGR,OACE,oBAAC,UAAD;EAAU,aAAU;EAAc,WAAU;EAC1C,UAAA,oBAAC,WAAD;GAAoB;GAAS,WAAU;GACrC,UAAA,qBAAC,QAAD;IAAM,WAAU;IAAhB,UAAA,CACG,aACC,oBAAC,UAAD;KACE,SAAS,UAAU;KACnB,kBAAkB,YAAY,UAAU,SAAS,YAAY,IAAI;KACjE,cAAY,EAAE,sBAAsB,EAAE,OAAO,MAAM,MAAM,GAAG,qBAAqB;IAClF,CAAA,GAEF,cACC,qBAAC,UAAD;KACE,MAAK;KACL,WAAU;KACV,iBAAe,CAAC;KAChB,cAAY,GAAG,YAAY,EAAE,yBAAyB,CAAC,GAAG,cAAc,IAAI,EAAE,2BAA2B,CAAC,GAAG,gBAAgB,EAAE,IAAI,MAAM;KACzI,SAAS;KALX,UAAA,CAOG,YACC,oBAAC,kBAAD;MAAkB,WAAU;MAAiC,eAAY;KAAQ,CAAA,IAEjF,oBAAC,MAAD;MACE,MAAK;MACL,UAAU;MACV,WAAU;MACV,eAAY;KACb,CAAA,GAEF,OACK;IAER,CAAA,IAAA,OAEE;;EACG,CAAA;CACH,CAAA;AAEd;;;;;AAMA,SAAgB,mBACd,OACsC;CACtC,MAAM,UAAU,MAAM,WAAW,GAAG,MAAM,SAAS,MAAM,GAAG,MAAM,SAAS,cAAc;CACzF,MAAM,CAAC,OAAO,YAAY,gBAAgB;EACxC;EACA,WAAW,uBAAuB,KAAK;CACzC,EAAE;CAEF,IAAI,MAAM,YAAY,SACpB,SAAS;EAAE;EAAS,WAAW,uBAAuB,KAAK;CAAE,CAAC;CAGhE,OAAO,CACL,MAAM,YACL,QACC,UAAU,aAAa;EACrB,GAAG;EACH,WAAW,qBAAqB,QAAQ,WAAW,GAAG;CACxD,EAAE,CACN;AACF;;AAGA,SAAgB,oBAAoB,OAA2D;CAC7F,MAAM,QAAQ,MAAM,kBAAkB,CAAC,EAAA,CAAG,KAAK,GAAG;CAElD,gBACQ,yBAAyB,MAAM,YAAY,OAAO,KAAK,MAAM,GAAG,IAAI,KAAA,CAAS,GACnF,CAAC,MAAM,YAAY,IAAI,CACzB;AACF"}
|
|
1
|
+
{"version":3,"file":"grouping.js","names":[],"sources":["../../../src/components/table/grouping.tsx"],"sourcesContent":["import type {\n ColumnSchema,\n TableRecordGroupSchema,\n TableSchema,\n TriggerButtonView,\n} from '@alfakit/core'\nimport {\n initialCollapsedGroups,\n registerTablePersistence,\n toggleCollapsedGroup,\n triggerButtonView,\n visitTable,\n} from '@alfakit/core'\nimport { ChevronDownIcon, ChevronRightIcon, LayersIcon } from 'lucide-react'\nimport { useEffect, useState } from 'react'\nimport { useT } from '../../context'\nimport { colorClass, textColorClasses } from '../../lib/colors'\nimport { Icon } from '../../lib/icons'\nimport { cn } from '../../lib/utils'\nimport { Checkbox } from '../ui/checkbox'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu'\nimport { TableCell, TableRow } from '../ui/table'\nimport { TableTriggerButton } from './trigger-button'\n\n/** The \"group by\" menu: one of the table's groups (or none) and the direction. */\nexport function TableGroupingMenu({ table }: { table: TableSchema }) {\n const t = useT()\n\n if (!table.groups || table.groups.length === 0) {\n return null\n }\n\n const active = table.grouping?.group ?? ''\n const groups = table.groups\n // `groupRecordsTriggerAction()`.\n const trigger = triggerButtonView(table, 'groupRecords', {\n label: t('table_grouping.group_by', {}, 'Group by'),\n })\n const changeGroup = (group: string) => visitTable(table.identifier, { group }, ['page'])\n const changeDirection = (direction: string) =>\n visitTable(table.identifier, { groupDirection: direction === 'desc' ? 'desc' : 'asc' }, [\n 'page',\n ])\n const inDropdownOnly = Boolean(table.groupingSettingsInDropdownOnDesktop)\n\n // Desktop default: the settings inline in the toolbar (the dropdown is for phones).\n const inline = inDropdownOnly ? null : (\n <div data-slot=\"table-grouping-inline\" className=\"hidden items-center gap-2 text-sm sm:flex\">\n <label className=\"flex items-center gap-2\">\n <span className=\"text-muted-foreground\">\n {t('table_grouping.group_by', {}, 'Group by')}\n </span>\n <select\n value={active}\n onChange={(event) => changeGroup(event.target.value)}\n className=\"border-input h-8 rounded-md border bg-transparent px-2 text-sm\"\n >\n <option value=\"\">{t('table_grouping.none', {}, 'No grouping')}</option>\n {groups.map((group) => (\n <option key={group.id} value={group.id}>\n {group.label}\n </option>\n ))}\n </select>\n </label>\n {table.grouping && !table.groupingDirectionSettingHidden && (\n <label className=\"flex items-center\">\n <span className=\"sr-only\">{t('table_grouping.direction', {}, 'Group direction')}</span>\n <select\n value={table.grouping.direction}\n onChange={(event) => changeDirection(event.target.value)}\n className=\"border-input h-8 rounded-md border bg-transparent px-2 text-sm\"\n >\n <option value=\"asc\">{t('table_grouping.ascending', {}, 'Ascending')}</option>\n <option value=\"desc\">{t('table_grouping.descending', {}, 'Descending')}</option>\n </select>\n </label>\n )}\n </div>\n )\n\n if (!trigger) return inline\n\n return (\n <>\n {inline}\n <div className={cn(!inDropdownOnly && 'sm:hidden')}>\n <TableGroupingDropdown\n table={table}\n groups={groups}\n trigger={trigger}\n active={active}\n onGroup={changeGroup}\n onDirection={changeDirection}\n />\n </div>\n </>\n )\n}\n\nfunction TableGroupingDropdown({\n table,\n groups,\n trigger,\n active,\n onGroup,\n onDirection,\n}: {\n table: TableSchema\n groups: NonNullable<TableSchema['groups']>\n trigger: TriggerButtonView\n active: string\n onGroup: (group: string) => void\n onDirection: (direction: string) => void\n}) {\n const t = useT()\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <TableTriggerButton\n view={trigger}\n defaultIcon={<Icon name=\"alfakit::tables.actions.group\" fallback={LayersIcon} />}\n responsiveLabel={!table.triggerActions?.groupRecords}\n active={Boolean(table.grouping)}\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"min-w-48\">\n <DropdownMenuLabel>{t('table_grouping.group_by', {}, 'Group by')}</DropdownMenuLabel>\n <DropdownMenuRadioGroup value={active} onValueChange={onGroup}>\n <DropdownMenuRadioItem value=\"\">\n {t('table_grouping.none', {}, 'No grouping')}\n </DropdownMenuRadioItem>\n {groups.map((group) => (\n <DropdownMenuRadioItem key={group.id} value={group.id}>\n {group.label}\n </DropdownMenuRadioItem>\n ))}\n </DropdownMenuRadioGroup>\n {table.grouping && !table.groupingDirectionSettingHidden && (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuLabel>\n {t('table_grouping.direction', {}, 'Group direction')}\n </DropdownMenuLabel>\n <DropdownMenuRadioGroup value={table.grouping.direction} onValueChange={onDirection}>\n <DropdownMenuRadioItem value=\"asc\">\n {t('table_grouping.ascending', {}, 'Ascending')}\n </DropdownMenuRadioItem>\n <DropdownMenuRadioItem value=\"desc\">\n {t('table_grouping.descending', {}, 'Descending')}\n </DropdownMenuRadioItem>\n </DropdownMenuRadioGroup>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\n\n/** A group heading row (`data-slot=\"table-group\"`), with a collapse toggle when collapsible. */\nexport function GroupHeaderRow({\n group,\n collapsed,\n collapsible,\n colSpan,\n onToggle,\n selection,\n}: {\n group: TableRecordGroupSchema\n collapsed: boolean\n collapsible: boolean\n colSpan: number\n onToggle: () => void\n /** `selectGroupsOnly()`: a checkbox selecting the group's records on the page. */\n selection?: { checked: boolean | 'indeterminate'; onChange: (checked: boolean) => void }\n}) {\n const t = useT()\n const text = (\n <span className=\"flex flex-col items-start\">\n <span className=\"font-medium\">{group.title}</span>\n {group.description && (\n <span className=\"text-muted-foreground text-xs font-normal\">{group.description}</span>\n )}\n </span>\n )\n // An enum group shows its `HasIcon` icon, in its `HasColor` colour, before the title.\n const content = group.icon ? (\n <span data-slot=\"table-group-title\" className=\"flex items-center gap-2\">\n <Icon\n name={group.icon}\n className={cn('size-4 shrink-0', colorClass(textColorClasses, group.color, 'gray'))}\n aria-hidden=\"true\"\n />\n {text}\n </span>\n ) : (\n text\n )\n\n return (\n <TableRow data-slot=\"table-group\" className=\"bg-muted/50 hover:bg-muted/50\">\n <TableCell colSpan={colSpan} className=\"py-2\">\n <span className=\"flex items-center gap-3\">\n {selection && (\n <Checkbox\n checked={selection.checked}\n onCheckedChange={(checked) => selection.onChange(checked === true)}\n aria-label={t('table.select_group', { group: group.title }, 'Select group :group')}\n />\n )}\n {collapsible ? (\n <button\n type=\"button\"\n className=\"focus-visible:ring-ring/50 flex items-center gap-2 rounded-sm text-start outline-none focus-visible:ring-[3px]\"\n aria-expanded={!collapsed}\n aria-label={`${collapsed ? t('table_grouping.expand', {}, 'Expand group') : t('table_grouping.collapse', {}, 'Collapse group')}: ${group.title}`}\n onClick={onToggle}\n >\n {collapsed ? (\n <ChevronRightIcon className=\"size-4 shrink-0 rtl:rotate-180\" aria-hidden=\"true\" />\n ) : (\n <Icon\n name=\"alfakit::tables.grouping.collapse-button\"\n fallback={ChevronDownIcon}\n className=\"size-4 shrink-0\"\n aria-hidden=\"true\"\n />\n )}\n {content}\n </button>\n ) : (\n content\n )}\n </span>\n </TableCell>\n </TableRow>\n )\n}\n\n/**\n * Collapsed group keys. Starts collapsed for `collapsedGroupsByDefault()` and resets when\n * the table is grouped differently.\n */\nexport function useCollapsedGroups(\n table: Pick<TableSchema, 'grouping' | 'recordGroups'>,\n): [Set<string>, (key: string) => void] {\n const groupId = table.grouping ? `${table.grouping.group}:${table.grouping.direction}` : ''\n const [state, setState] = useState(() => ({\n groupId,\n collapsed: initialCollapsedGroups(table),\n }))\n\n if (state.groupId !== groupId) {\n setState({ groupId, collapsed: initialCollapsedGroups(table) })\n }\n\n return [\n state.collapsed,\n (key: string) =>\n setState((current) => ({\n ...current,\n collapsed: toggleCollapsedGroup(current.collapsed, key),\n })),\n ]\n}\n\n/** Register the table's session-persisted keys so cleared values are sent explicitly. */\nexport function useTablePersistence(table: Pick<TableSchema, 'identifier' | 'persistedState'>) {\n const keys = (table.persistedState ?? []).join(',')\n\n useEffect(\n () => registerTablePersistence(table.identifier, keys ? keys.split(',') : undefined),\n [table.identifier, keys],\n )\n}\n\n/** Number of cells in a row of `columns` plus leading and trailing cells. */\nexport function rowCellCount(columns: ColumnSchema[], leading: number, trailing: number): number {\n return columns.length + leading + trailing\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Component styles shared by panels (themes.css) and by Alfakit outside panels
|
|
3
|
+
* (standalone.css, starter-kit panels): chart colours, RichEditor columns, the calendar,
|
|
4
|
+
* tree and Kanban plugins, and field positioning. They read the theme tokens (`--primary`,
|
|
5
|
+
* `--border`…), whichever stylesheet defines them. Copied into each renderer's dist.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/* ------------------------------------------------------------------ Charts */
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* Chart.js paints axes, legends and tooltips on the canvas, so chart widgets read these
|
|
12
|
+
* properties from <html> (re-read when the theme or dark mode changes). Colours take any
|
|
13
|
+
* CSS colour; the widths and radius are unitless numbers. Override them in a theme:
|
|
14
|
+
* :root[data-alfakit-theme~='acme'] { --chart-tooltip-bg: oklch(0.2 0 0); }
|
|
15
|
+
* Stat sparklines (`[data-slot='stat-chart']`) use the `--stat-chart-*` properties.
|
|
16
|
+
*/
|
|
17
|
+
:root {
|
|
18
|
+
--chart-text: var(--muted-foreground);
|
|
19
|
+
--chart-grid: var(--border);
|
|
20
|
+
--chart-legend-foreground: var(--muted-foreground);
|
|
21
|
+
--chart-tooltip-bg: var(--popover);
|
|
22
|
+
--chart-tooltip-foreground: var(--popover-foreground);
|
|
23
|
+
--chart-tooltip-border: var(--border);
|
|
24
|
+
--chart-tooltip-border-width: 1;
|
|
25
|
+
--chart-tooltip-radius: 6;
|
|
26
|
+
--stat-chart-stroke-width: 2;
|
|
27
|
+
--stat-chart-fill-opacity: 0.12;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
* RichEditor `grid` column blocks and `lead` / `small` text, in the editor and in rendered
|
|
32
|
+
* content (`RichContentRenderer`). Columns stack on small screens. Stored as
|
|
33
|
+
* `<div data-type="grid" class="alfakit-grid alfakit-grid-cols-2"><div data-type="gridColumn">`
|
|
34
|
+
* and `<p class="alfakit-lead">`; copy these rules when showing content outside a panel.
|
|
35
|
+
*/
|
|
36
|
+
:where(.alfakit-grid) {
|
|
37
|
+
display: grid;
|
|
38
|
+
gap: 1rem;
|
|
39
|
+
grid-template-columns: minmax(0, 1fr);
|
|
40
|
+
margin-block: 0.5rem;
|
|
41
|
+
}
|
|
42
|
+
:where(.alfakit-grid-column) {
|
|
43
|
+
min-width: 0;
|
|
44
|
+
}
|
|
45
|
+
:where(.alfakit-grid-column) > :first-child {
|
|
46
|
+
margin-block-start: 0;
|
|
47
|
+
}
|
|
48
|
+
@media (min-width: 768px) {
|
|
49
|
+
:where(.alfakit-grid-cols-2) {
|
|
50
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
51
|
+
}
|
|
52
|
+
:where(.alfakit-grid-cols-3) {
|
|
53
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
54
|
+
}
|
|
55
|
+
:where(.alfakit-grid-cols-4) {
|
|
56
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
57
|
+
}
|
|
58
|
+
:where(.alfakit-grid-cols-5) {
|
|
59
|
+
grid-template-columns: repeat(5, minmax(0, 1fr));
|
|
60
|
+
}
|
|
61
|
+
:where(.alfakit-grid-cols-6) {
|
|
62
|
+
grid-template-columns: repeat(6, minmax(0, 1fr));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
:where([contenteditable] .alfakit-grid-column) {
|
|
66
|
+
border: 1px dashed var(--border);
|
|
67
|
+
border-radius: 0.375rem;
|
|
68
|
+
padding: 0.25rem 0.5rem;
|
|
69
|
+
}
|
|
70
|
+
:where(.alfakit-lead) {
|
|
71
|
+
font-size: 1.125em;
|
|
72
|
+
line-height: 1.6;
|
|
73
|
+
}
|
|
74
|
+
:where(.alfakit-prose small) {
|
|
75
|
+
font-size: 0.8125em;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* ---------------------------------------------------------- Calendar and tree */
|
|
79
|
+
|
|
80
|
+
/*
|
|
81
|
+
* The calendar widget (alfasix/alfakit-calendar) draws FullCalendar inside
|
|
82
|
+
* `[data-slot="calendar"]`; FullCalendar reads these `--fc-*` variables, so every theme's
|
|
83
|
+
* tokens (and dark mode) apply. Override them on the slot to restyle one calendar.
|
|
84
|
+
*/
|
|
85
|
+
:where(.fc[data-slot='calendar']) {
|
|
86
|
+
--fc-small-font-size: 0.75rem;
|
|
87
|
+
--fc-page-bg-color: var(--card);
|
|
88
|
+
--fc-neutral-bg-color: var(--muted);
|
|
89
|
+
--fc-neutral-text-color: var(--muted-foreground);
|
|
90
|
+
--fc-border-color: var(--border);
|
|
91
|
+
--fc-button-text-color: var(--foreground);
|
|
92
|
+
--fc-button-bg-color: var(--background);
|
|
93
|
+
--fc-button-border-color: var(--border);
|
|
94
|
+
--fc-button-hover-bg-color: var(--accent);
|
|
95
|
+
--fc-button-hover-border-color: var(--border);
|
|
96
|
+
--fc-button-active-bg-color: var(--secondary);
|
|
97
|
+
--fc-button-active-border-color: var(--border);
|
|
98
|
+
--fc-event-bg-color: var(--primary);
|
|
99
|
+
--fc-event-border-color: var(--primary);
|
|
100
|
+
--fc-event-text-color: var(--primary-foreground);
|
|
101
|
+
--fc-event-selected-overlay-color: color-mix(in oklab, var(--foreground) 25%, transparent);
|
|
102
|
+
--fc-more-link-bg-color: var(--muted);
|
|
103
|
+
--fc-more-link-text-color: var(--foreground);
|
|
104
|
+
--fc-non-business-color: color-mix(in oklab, var(--muted) 60%, transparent);
|
|
105
|
+
--fc-bg-event-color: var(--primary);
|
|
106
|
+
--fc-bg-event-opacity: 0.2;
|
|
107
|
+
--fc-highlight-color: color-mix(in oklab, var(--primary) 15%, transparent);
|
|
108
|
+
--fc-today-bg-color: color-mix(in oklab, var(--primary) 6%, transparent);
|
|
109
|
+
--fc-now-indicator-color: var(--destructive);
|
|
110
|
+
--fc-list-event-hover-bg-color: var(--accent);
|
|
111
|
+
color: var(--card-foreground);
|
|
112
|
+
}
|
|
113
|
+
/*
|
|
114
|
+
* FullCalendar puts its `fc` class on the slot element itself and injects its own CSS
|
|
115
|
+
* (`.fc .fc-button`, two classes), so these rules are plain selectors anchored on
|
|
116
|
+
* `.fc[data-slot='calendar']` (three) rather than `:where()`, which would always lose.
|
|
117
|
+
* Restyle one calendar with a more specific selector or with the `--fc-*` variables.
|
|
118
|
+
*/
|
|
119
|
+
.fc[data-slot='calendar'] .fc-toolbar-title {
|
|
120
|
+
font-size: 1.125rem;
|
|
121
|
+
font-weight: 600;
|
|
122
|
+
line-height: 1.75rem;
|
|
123
|
+
color: var(--foreground);
|
|
124
|
+
}
|
|
125
|
+
.fc[data-slot='calendar'] .fc-button {
|
|
126
|
+
display: inline-flex;
|
|
127
|
+
align-items: center;
|
|
128
|
+
justify-content: center;
|
|
129
|
+
min-height: 2.25rem;
|
|
130
|
+
padding: 0.375rem 0.75rem;
|
|
131
|
+
border-radius: var(--radius);
|
|
132
|
+
font-size: 0.875rem;
|
|
133
|
+
font-weight: 500;
|
|
134
|
+
line-height: 1.25rem;
|
|
135
|
+
box-shadow: none;
|
|
136
|
+
text-transform: capitalize;
|
|
137
|
+
}
|
|
138
|
+
.fc[data-slot='calendar'] .fc-button .fc-icon {
|
|
139
|
+
font-size: 1.125rem;
|
|
140
|
+
}
|
|
141
|
+
.fc[data-slot='calendar'] .fc-button-group > .fc-button:not(:first-child) {
|
|
142
|
+
border-start-start-radius: 0;
|
|
143
|
+
border-end-start-radius: 0;
|
|
144
|
+
}
|
|
145
|
+
.fc[data-slot='calendar'] .fc-button-group > .fc-button:not(:last-child) {
|
|
146
|
+
border-start-end-radius: 0;
|
|
147
|
+
border-end-end-radius: 0;
|
|
148
|
+
}
|
|
149
|
+
.fc[data-slot='calendar'] .fc-button-primary:disabled {
|
|
150
|
+
opacity: 0.5;
|
|
151
|
+
}
|
|
152
|
+
.fc[data-slot='calendar'] .fc-button-primary:not(:disabled).fc-button-active,
|
|
153
|
+
.fc[data-slot='calendar'] .fc-button-primary:not(:disabled):active {
|
|
154
|
+
color: var(--secondary-foreground);
|
|
155
|
+
}
|
|
156
|
+
.fc[data-slot='calendar'] .fc-button-primary:focus,
|
|
157
|
+
.fc[data-slot='calendar'] .fc-button-primary:not(:disabled).fc-button-active:focus,
|
|
158
|
+
.fc[data-slot='calendar'] .fc-button-primary:not(:disabled):active:focus {
|
|
159
|
+
box-shadow: none;
|
|
160
|
+
}
|
|
161
|
+
.fc[data-slot='calendar'] .fc-button:focus-visible {
|
|
162
|
+
outline: 2px solid var(--ring);
|
|
163
|
+
outline-offset: 2px;
|
|
164
|
+
z-index: 2;
|
|
165
|
+
}
|
|
166
|
+
.fc[data-slot='calendar'] a {
|
|
167
|
+
color: inherit;
|
|
168
|
+
}
|
|
169
|
+
.fc[data-slot='calendar'] .fc-daygrid-day-number,
|
|
170
|
+
.fc[data-slot='calendar'] .fc-col-header-cell-cushion {
|
|
171
|
+
text-decoration: none;
|
|
172
|
+
}
|
|
173
|
+
.fc[data-slot='calendar'] .fc-col-header-cell-cushion {
|
|
174
|
+
padding-block: 0.375rem;
|
|
175
|
+
font-size: 0.75rem;
|
|
176
|
+
font-weight: 500;
|
|
177
|
+
color: var(--muted-foreground);
|
|
178
|
+
}
|
|
179
|
+
.fc[data-slot='calendar'] .fc-daygrid-day-number {
|
|
180
|
+
font-size: 0.875rem;
|
|
181
|
+
}
|
|
182
|
+
.fc[data-slot='calendar'] .fc-day-other .fc-daygrid-day-number {
|
|
183
|
+
color: var(--muted-foreground);
|
|
184
|
+
}
|
|
185
|
+
/* Today: a tinted cell (`--fc-today-bg-color`) and the date in a primary pill. */
|
|
186
|
+
.fc[data-slot='calendar'] .fc-daygrid-day.fc-day-today .fc-daygrid-day-number {
|
|
187
|
+
display: inline-flex;
|
|
188
|
+
align-items: center;
|
|
189
|
+
justify-content: center;
|
|
190
|
+
min-width: 1.75rem;
|
|
191
|
+
height: 1.75rem;
|
|
192
|
+
margin: 0.25rem;
|
|
193
|
+
padding: 0 0.375rem;
|
|
194
|
+
border-radius: 9999px;
|
|
195
|
+
background: var(--primary);
|
|
196
|
+
color: var(--primary-foreground);
|
|
197
|
+
font-weight: 600;
|
|
198
|
+
}
|
|
199
|
+
.fc[data-slot='calendar'] .fc-col-header-cell.fc-day-today .fc-col-header-cell-cushion {
|
|
200
|
+
color: var(--primary);
|
|
201
|
+
font-weight: 600;
|
|
202
|
+
}
|
|
203
|
+
.fc[data-slot='calendar'] .fc-event {
|
|
204
|
+
border-radius: min(var(--radius), 0.375rem);
|
|
205
|
+
}
|
|
206
|
+
.fc[data-slot='calendar'] .fc-daygrid-event,
|
|
207
|
+
.fc[data-slot='calendar'] .fc-timegrid-event .fc-event-main,
|
|
208
|
+
.fc[data-slot='calendar'] .fc-list-event td {
|
|
209
|
+
font-size: 0.75rem;
|
|
210
|
+
}
|
|
211
|
+
/* Clipped titles keep their beginning and end with an ellipsis, also a Latin title in a
|
|
212
|
+
right-to-left calendar (its direction follows its own text). */
|
|
213
|
+
.fc[data-slot='calendar'] .fc-event-title {
|
|
214
|
+
text-overflow: ellipsis;
|
|
215
|
+
unicode-bidi: plaintext;
|
|
216
|
+
text-align: start;
|
|
217
|
+
}
|
|
218
|
+
.fc[data-slot='calendar'] .fc-daygrid-dot-event:hover,
|
|
219
|
+
.fc[data-slot='calendar'] .fc-daygrid-dot-event.fc-event-mirror {
|
|
220
|
+
background: var(--accent);
|
|
221
|
+
}
|
|
222
|
+
.fc[data-slot='calendar'] .fc-list-day-cushion,
|
|
223
|
+
.fc[data-slot='calendar'] .fc-popover-header {
|
|
224
|
+
color: var(--foreground);
|
|
225
|
+
}
|
|
226
|
+
.fc[data-slot='calendar'] .fc-popover {
|
|
227
|
+
border-radius: var(--radius);
|
|
228
|
+
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
|
|
229
|
+
overflow: hidden;
|
|
230
|
+
}
|
|
231
|
+
.fc[data-slot='calendar'] .fc-timegrid-slot-label,
|
|
232
|
+
.fc[data-slot='calendar'] .fc-timegrid-axis,
|
|
233
|
+
.fc[data-slot='calendar'] .fc-list-event-time {
|
|
234
|
+
color: var(--muted-foreground);
|
|
235
|
+
font-size: 0.75rem;
|
|
236
|
+
}
|
|
237
|
+
/*
|
|
238
|
+
* The list view hides its column headers for screen readers with `left: -10000px`. Right to
|
|
239
|
+
* left that is scrollable overflow: the whole page gains a 10 000 px horizontal scroll and the
|
|
240
|
+
* top bar slides under the sidebar. Clip it in place instead (still read by screen readers).
|
|
241
|
+
*/
|
|
242
|
+
.fc[data-slot='calendar'] .fc-list-table thead {
|
|
243
|
+
left: auto;
|
|
244
|
+
inset-inline-start: 0;
|
|
245
|
+
width: 1px;
|
|
246
|
+
height: 1px;
|
|
247
|
+
overflow: hidden;
|
|
248
|
+
clip-path: inset(50%);
|
|
249
|
+
white-space: nowrap;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/*
|
|
253
|
+
* Fields contain what they position. Headless switches, checkboxes and radios render a
|
|
254
|
+
* visually hidden native input beside the control, absolutely positioned (and shifted by
|
|
255
|
+
* -100%); without a positioned field it lands at the page edge and, right to left, widens
|
|
256
|
+
* the page on phones.
|
|
257
|
+
*/
|
|
258
|
+
:where([data-slot='field']) {
|
|
259
|
+
position: relative;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/*
|
|
263
|
+
* Narrow screens: FullCalendar keeps its header toolbar on one row, wider than a phone.
|
|
264
|
+
* Its chunks (navigation, title, views) wrap instead, and the title shrinks. Flex gaps and
|
|
265
|
+
* `justify-content` follow the writing direction, so this works right to left too. (Plain
|
|
266
|
+
* selectors: FullCalendar injects its own CSS, which would beat `:where()`; the slot is
|
|
267
|
+
* the `.fc` element itself.)
|
|
268
|
+
*/
|
|
269
|
+
@media (max-width: 39.99rem) {
|
|
270
|
+
[data-slot='calendar'] .fc-toolbar.fc-header-toolbar {
|
|
271
|
+
flex-wrap: wrap;
|
|
272
|
+
gap: 0.5rem;
|
|
273
|
+
}
|
|
274
|
+
[data-slot='calendar'] .fc-toolbar .fc-toolbar-chunk {
|
|
275
|
+
display: flex;
|
|
276
|
+
flex-wrap: wrap;
|
|
277
|
+
align-items: center;
|
|
278
|
+
gap: 0.25rem;
|
|
279
|
+
min-width: 0;
|
|
280
|
+
}
|
|
281
|
+
[data-slot='calendar'] .fc-toolbar .fc-toolbar-title {
|
|
282
|
+
font-size: 1rem;
|
|
283
|
+
overflow-wrap: anywhere;
|
|
284
|
+
}
|
|
285
|
+
[data-slot='calendar'] .fc-toolbar .fc-button {
|
|
286
|
+
font-size: 0.8125rem;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/*
|
|
291
|
+
* The tree (alfasix/alfakit-tree): the drop indicator while dragging. Rows carry
|
|
292
|
+
* `data-drop="before|after|inside"`; lines are drawn above or below the row, so they
|
|
293
|
+
* need no direction.
|
|
294
|
+
*/
|
|
295
|
+
:where([data-slot='tree-item'][data-drop='before']) {
|
|
296
|
+
box-shadow: inset 0 2px 0 0 var(--primary);
|
|
297
|
+
}
|
|
298
|
+
:where([data-slot='tree-item'][data-drop='after']) {
|
|
299
|
+
box-shadow: inset 0 -2px 0 0 var(--primary);
|
|
300
|
+
}
|
|
301
|
+
:where([data-slot='tree-item'][data-drop='inside']) {
|
|
302
|
+
background-color: color-mix(in oklab, var(--primary) 10%, transparent);
|
|
303
|
+
outline: 1px dashed var(--primary);
|
|
304
|
+
outline-offset: -1px;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/*
|
|
308
|
+
* The Kanban board (alfasix/alfakit-kanban). A card being dragged leaves a dashed
|
|
309
|
+
* placeholder (`data-picked="pointer"`) while a copy follows the pointer
|
|
310
|
+
* (`data-slot="kanban-ghost"`); a card picked up with the keyboard is lifted
|
|
311
|
+
* (`data-picked="keyboard"`). A list the picked card may not enter has `data-refused`.
|
|
312
|
+
*/
|
|
313
|
+
:where([data-slot='kanban-card'][data-picked='pointer']) {
|
|
314
|
+
opacity: 0.45;
|
|
315
|
+
}
|
|
316
|
+
:where([data-slot='kanban-card'][data-picked='pointer'] > [data-slot='kanban-card-body']) {
|
|
317
|
+
border-style: dashed;
|
|
318
|
+
box-shadow: none;
|
|
319
|
+
}
|
|
320
|
+
:where([data-slot='kanban-card'][data-picked='keyboard'] > [data-slot='kanban-card-body']) {
|
|
321
|
+
outline: 2px solid var(--primary);
|
|
322
|
+
outline-offset: 2px;
|
|
323
|
+
box-shadow: 0 10px 24px -12px color-mix(in oklab, var(--foreground) 45%, transparent);
|
|
324
|
+
}
|
|
325
|
+
:where([data-slot='kanban-card'][data-saving]) {
|
|
326
|
+
opacity: 0.7;
|
|
327
|
+
}
|
|
328
|
+
:where([data-slot='kanban-ghost']) {
|
|
329
|
+
cursor: grabbing;
|
|
330
|
+
list-style: none;
|
|
331
|
+
box-shadow: 0 18px 40px -16px color-mix(in oklab, var(--foreground) 55%, transparent);
|
|
332
|
+
}
|
|
333
|
+
:where([data-slot='kanban-dropzone'][data-refused]) {
|
|
334
|
+
background-color: color-mix(in oklab, var(--destructive) 8%, transparent);
|
|
335
|
+
outline: 1px dashed var(--destructive);
|
|
336
|
+
outline-offset: -1px;
|
|
337
|
+
}
|
|
338
|
+
:where(body[data-kanban-dragging]) {
|
|
339
|
+
cursor: grabbing;
|
|
340
|
+
user-select: none;
|
|
341
|
+
-webkit-user-select: none;
|
|
342
|
+
}
|
|
343
|
+
@media (prefers-reduced-motion: reduce) {
|
|
344
|
+
:where([data-slot='kanban-card'] > [data-slot='kanban-card-body']) {
|
|
345
|
+
transition: none;
|
|
346
|
+
}
|
|
347
|
+
}
|
package/dist/eject-manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"package": "@alfakit/react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"adapter": "react",
|
|
5
|
-
"generatedAt": "2026-10-
|
|
5
|
+
"generatedAt": "2026-10-19T11:53:55.687Z",
|
|
6
6
|
"components": {
|
|
7
7
|
"TextInput": {
|
|
8
8
|
"file": "src/components/fields/text-input.tsx",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alfakit-toaster.d.ts","names":[],"sources":["../../src/standalone/alfakit-toaster.tsx"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"alfakit-toaster.d.ts","names":[],"sources":["../../src/standalone/alfakit-toaster.tsx"],"mappings":";;iBAOiB;;EAEf,WAAW;EACX;;;;;EAKA;;EAEA;;;;;;;;;;;wBAYc,iBACd,UACA,KACA,SACA,WACC,sCAAmB,IAAA"}
|