@plexui/ui 0.20.15 → 0.21.0
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/dist/es/components/FieldError/FieldError.js +1 -1
- package/dist/es/components/FieldError/FieldError.js.map +1 -1
- package/dist/es/components/RadioGroup/RadioGroup.js +4 -3
- package/dist/es/components/RadioGroup/RadioGroup.js.map +1 -1
- package/dist/es/components/Sortable/Sortable.js +33 -0
- package/dist/es/components/Sortable/Sortable.js.map +1 -0
- package/dist/es/components/Sortable/index.js +2 -0
- package/dist/es/components/Sortable/index.js.map +1 -0
- package/dist/es/components/Tabs/Tabs.js +9 -8
- package/dist/es/components/Tabs/Tabs.js.map +1 -1
- package/dist/es/components/TagInput/TagInput.js +2 -2
- package/dist/es/components/TagInput/TagInput.js.map +1 -1
- package/dist/es/components/Textarea/Textarea.js.map +1 -1
- package/dist/es/lib/sortable.js +406 -0
- package/dist/es/lib/sortable.js.map +1 -0
- package/dist/types/components/RadioGroup/RadioGroup.d.ts +8 -2
- package/dist/types/components/Sortable/Sortable.d.ts +51 -0
- package/dist/types/components/Sortable/index.d.ts +1 -0
- package/dist/types/components/TagInput/TagInput.d.ts +6 -1
- package/dist/types/components/Textarea/Textarea.d.ts +1 -1
- package/dist/types/lib/sortable.d.ts +9 -0
- package/package.json +1 -1
|
@@ -3,6 +3,6 @@ import clsx from "clsx";
|
|
|
3
3
|
import { ExclamationMarkCircle } from "../Icon/index.js";
|
|
4
4
|
import s from "@plexui/styles/components/FieldError/FieldError.module.css";
|
|
5
5
|
export function FieldError({ children, className, id, icon = true }) {
|
|
6
|
-
return (
|
|
6
|
+
return (_jsx("div", { className: clsx(s.FieldError, className), id: id, role: "alert", children: _jsxs("div", { className: s.Inner, children: [icon && _jsx(ExclamationMarkCircle, { className: s.Icon }), _jsx("span", { children: children })] }) }));
|
|
7
7
|
}
|
|
8
8
|
//# sourceMappingURL=FieldError.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldError.js","sourceRoot":"","sources":["../../../../src/components/FieldError/FieldError.tsx"],"names":[],"mappings":";AAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAE/C,OAAO,CAAC,MAAM,4DAA4D,CAAA;AAc1E,MAAM,UAAU,UAAU,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,GAAG,IAAI,EAAmB;IAClF,OAAO,CACL,
|
|
1
|
+
{"version":3,"file":"FieldError.js","sourceRoot":"","sources":["../../../../src/components/FieldError/FieldError.tsx"],"names":[],"mappings":";AAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAE/C,OAAO,CAAC,MAAM,4DAA4D,CAAA;AAc1E,MAAM,UAAU,UAAU,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,GAAG,IAAI,EAAmB;IAClF,OAAO,CACL,cAAK,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAC,OAAO,YACjE,eAAK,SAAS,EAAE,CAAC,CAAC,KAAK,aACpB,IAAI,IAAI,KAAC,qBAAqB,IAAC,SAAS,EAAE,CAAC,CAAC,IAAI,GAAI,EACrD,yBAAO,QAAQ,GAAQ,IACnB,GACF,CACP,CAAA;AACH,CAAC","sourcesContent":["import clsx from \"clsx\"\n\nimport { ExclamationMarkCircle } from \"../Icon\"\n\nimport s from \"@plexui/styles/components/FieldError/FieldError.module.css\"\n\nexport type FieldErrorProps = {\n children: React.ReactNode\n className?: string\n id?: string\n /**\n * Shows the error icon before the message. Turn it off where the message\n * stands alone, such as under a centered code input.\n * @default true\n */\n icon?: boolean\n}\n\nexport function FieldError({ children, className, id, icon = true }: FieldErrorProps) {\n return (\n <div className={clsx(s.FieldError, className)} id={id} role=\"alert\">\n <div className={s.Inner}>\n {icon && <ExclamationMarkCircle className={s.Icon} />}\n <span>{children}</span>\n </div>\n </div>\n )\n}\n"]}
|
|
@@ -19,16 +19,17 @@ export const RadioGroup = ({ onChange, children, className, direction = "row", d
|
|
|
19
19
|
}), [disabled, direction]);
|
|
20
20
|
return (_jsx(RadioGroupContext, { value: store, children: _jsx(RadixRadioGroup.Root, { className: clsx(s.RadioGroup, className), "data-direction": direction, onValueChange: onChange, disabled: disabled, ...restProps, children: children }) }));
|
|
21
21
|
};
|
|
22
|
-
const Item = ({ value, disabled: itemDisabled = false, required, children, description, className, block = false, orientation = "left", ...restProps }) => {
|
|
22
|
+
const Item = ({ value, disabled: itemDisabled = false, required, children, description, className, block = false, orientation = "left", id: idProp, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, ...restProps }) => {
|
|
23
23
|
const { disabled: groupDisabled } = useRadioGroupContext();
|
|
24
24
|
const disabled = groupDisabled || itemDisabled;
|
|
25
25
|
const id = useId();
|
|
26
|
-
|
|
26
|
+
// These name the radio itself: a `Field` around the item labels it through them
|
|
27
|
+
const itemId = idProp ?? `${value}-${id}`;
|
|
27
28
|
const descriptionId = description ? `${itemId}-description` : undefined;
|
|
28
29
|
const label = (_jsxs("label", { htmlFor: itemId, className: clsx(s.RadioLabel, className), "data-disabled": disabled ? "" : undefined, "data-block": block ? "" : undefined, "data-orientation": orientation, onMouseDown: (event) => {
|
|
29
30
|
if (!event.defaultPrevented && event.detail > 1)
|
|
30
31
|
event.preventDefault();
|
|
31
|
-
}, children: [_jsx("div", { className: s.RadioIndicatorWrapper, children: _jsx(RadixRadioGroup.Item, { id: itemId, value: value, disabled: disabled, required: required, className: s.RadioItem, "aria-describedby": descriptionId, children: _jsx(RadixRadioGroup.Indicator, { className: s.RadioIndicator }) }) }), children] }));
|
|
32
|
+
}, children: [_jsx("div", { className: s.RadioIndicatorWrapper, children: _jsx(RadixRadioGroup.Item, { id: itemId, value: value, disabled: disabled, required: required, className: s.RadioItem, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": [descriptionId, ariaDescribedBy].filter(Boolean).join(" ") || undefined, children: _jsx(RadixRadioGroup.Indicator, { className: s.RadioIndicator }) }) }), children] }));
|
|
32
33
|
return (
|
|
33
34
|
// Providing an extra wrapper enables `label` to be inline-flex, avoiding clickable whitespace
|
|
34
35
|
// when radio options are of varied lengths.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RadioGroup.js","sourceRoot":"","sources":["../../../../src/components/RadioGroup/RadioGroup.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,UAAU,IAAI,eAAe,EAAE,MAAM,UAAU,CAAA;AACxD,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AACjE,OAAO,CAAC,MAAM,4DAA4D,CAAA;AAS1E,MAAM,iBAAiB,GAAG,aAAa,CAAgC,IAAI,CAAC,CAAA;AAE5E,MAAM,oBAAoB,GAAG,GAAG,EAAE;IAChC,MAAM,OAAO,GAAG,GAAG,CAAC,iBAAiB,CAAC,CAAA;IAEtC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAA;IAC5E,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA;AAqBD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAmB,EAC3C,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,SAAS,GAAG,KAAK,EACjB,QAAQ,GAAG,KAAK,EAChB,GAAG,SAAS,EACO,EAAE,EAAE;IACvB,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,CAAC;QACL,QAAQ;QACR,SAAS;KACV,CAAC,EACF,CAAC,QAAQ,EAAE,SAAS,CAAC,CACtB,CAAA;IAED,OAAO,CACL,KAAC,iBAAiB,IAAC,KAAK,EAAE,KAAK,YAC7B,KAAC,eAAe,CAAC,IAAI,IACnB,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,SAAS,CAAC,oBACxB,SAAS,EACzB,aAAa,EAAE,QAAQ,EACvB,QAAQ,EAAE,QAAQ,KACd,SAAS,YAEZ,QAAQ,GACY,GACL,CACrB,CAAA;AACH,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"RadioGroup.js","sourceRoot":"","sources":["../../../../src/components/RadioGroup/RadioGroup.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { RadioGroup as RadixRadioGroup } from \"radix-ui\"\nimport React, { createContext, use, useId, useMemo } from \"react\"\nimport s from \"@plexui/styles/components/RadioGroup/RadioGroup.module.css\"\n\ntype Direction = \"col\" | \"row\"\n\ntype RadioGroupContextValue = {\n disabled: boolean\n direction: Direction\n}\n\nconst RadioGroupContext = createContext<RadioGroupContextValue | null>(null)\n\nconst useRadioGroupContext = () => {\n const context = use(RadioGroupContext)\n\n if (!context) {\n throw new Error(\"RadioGroup components must be wrapped in <RadioGroup />\")\n }\n\n return context\n}\n\nexport type RadioGroupProps<T extends string> = {\n \"defaultValue\"?: T\n \"value\"?: T\n \"name\"?: string\n \"onChange\"?: (value: T) => void\n /** Accessible label for the radio options */\n \"aria-label\"?: string\n /** Determines the layout direction of the radio items\n * @default row\n */\n \"direction\"?: Direction\n /** Controls whether the entire radio group is disabled */\n \"disabled\"?: boolean\n /** Class applied to the radio group container */\n \"className\"?: string\n \"children\": React.ReactNode\n \"required\"?: boolean\n}\n\nexport const RadioGroup = <T extends string>({\n onChange,\n children,\n className,\n direction = \"row\",\n disabled = false,\n ...restProps\n}: RadioGroupProps<T>) => {\n const store = useMemo<RadioGroupContextValue>(\n () => ({\n disabled,\n direction,\n }),\n [disabled, direction],\n )\n\n return (\n <RadioGroupContext value={store}>\n <RadixRadioGroup.Root\n className={clsx(s.RadioGroup, className)}\n data-direction={direction}\n onValueChange={onChange}\n disabled={disabled}\n {...restProps}\n >\n {children}\n </RadixRadioGroup.Root>\n </RadioGroupContext>\n )\n}\n\nexport type RadioGroupItemProps<T extends string> = {\n value: T\n /** Determines if a given radio item is disabled */\n disabled?: boolean\n required?: boolean\n block?: boolean\n className?: string\n /**\n * The orientation of the radio indicator relative to the label.\n *\n * @default \"left\"\n */\n orientation?: \"left\" | \"right\"\n /** Id of the radio, so a label outside the item can target it with `htmlFor` */\n id?: string\n \"aria-label\"?: string\n \"aria-labelledby\"?: string\n \"aria-describedby\"?: string\n /** The option's label. Leave it out when a `Field` around the item names it. */\n children?: React.ReactNode\n /** Optional second line below the option's label. Linked via `aria-describedby`. */\n description?: React.ReactNode\n}\n\nconst Item = <T extends string>({\n value,\n disabled: itemDisabled = false,\n required,\n children,\n description,\n className,\n block = false,\n orientation = \"left\",\n id: idProp,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n ...restProps\n}: RadioGroupItemProps<T>) => {\n const { disabled: groupDisabled } = useRadioGroupContext()\n const disabled = groupDisabled || itemDisabled\n\n const id = useId()\n // These name the radio itself: a `Field` around the item labels it through them\n const itemId = idProp ?? `${value}-${id}`\n const descriptionId = description ? `${itemId}-description` : undefined\n\n const label = (\n <label\n htmlFor={itemId}\n className={clsx(s.RadioLabel, className)}\n data-disabled={disabled ? \"\" : undefined}\n data-block={block ? \"\" : undefined}\n data-orientation={orientation}\n onMouseDown={(event) => {\n if (!event.defaultPrevented && event.detail > 1) event.preventDefault()\n }}\n >\n <div className={s.RadioIndicatorWrapper}>\n <RadixRadioGroup.Item\n id={itemId}\n value={value}\n disabled={disabled}\n required={required}\n className={s.RadioItem}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={[descriptionId, ariaDescribedBy].filter(Boolean).join(\" \") || undefined}\n >\n <RadixRadioGroup.Indicator className={s.RadioIndicator} />\n </RadixRadioGroup.Item>\n </div>\n {children}\n </label>\n )\n\n return (\n // Providing an extra wrapper enables `label` to be inline-flex, avoiding clickable whitespace\n // when radio options are of varied lengths.\n // NOTE: Important that this is `flex` to prevent the `inline-flex` label from extra, unintentional whitespace.\n <div className={clsx(\"flex\", block && \"w-full\")} {...restProps}>\n {description ? (\n // The description stays outside the label, so it describes the radio instead of naming it\n <div className={s.RadioItemGroup} data-block={block ? \"\" : undefined} data-orientation={orientation}>\n {label}\n <span id={descriptionId} className={s.RadioDescription} data-disabled={disabled ? \"\" : undefined}>\n {description}\n </span>\n </div>\n ) : (\n label\n )}\n </div>\n )\n}\n\nRadioGroup.Item = Item\n"]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { flushSync } from "react-dom";
|
|
5
|
+
import { useLatestValue } from "../../hooks/useLatestValue.js";
|
|
6
|
+
import { moveItem, sortableKeyDown, sortablePointerDown } from "../../lib/sortable.js";
|
|
7
|
+
import { GripVertical } from "../Icon/index.js";
|
|
8
|
+
import s from "@plexui/styles/components/Sortable/Sortable.module.css";
|
|
9
|
+
const preventNativeDrag = (event) => event.preventDefault();
|
|
10
|
+
/** Reorders its direct children by dragging, from anywhere but a control, or by a `Sortable.Handle` where grips are shown. */
|
|
11
|
+
export function Sortable({ value, onChange, layout = "list", as: Tag = "div", disabled = false, handles, className, children, onPointerDown, onKeyDown, ...rest }) {
|
|
12
|
+
const latest = useLatestValue({ value, onChange });
|
|
13
|
+
const commit = (from, to) => {
|
|
14
|
+
flushSync(() => latest.current.onChange?.(moveItem(latest.current.value, from, to)));
|
|
15
|
+
};
|
|
16
|
+
const handlePointerDown = (event) => {
|
|
17
|
+
onPointerDown?.(event);
|
|
18
|
+
if (!disabled)
|
|
19
|
+
sortablePointerDown(event.nativeEvent, event.currentTarget, layout, commit);
|
|
20
|
+
};
|
|
21
|
+
const handleKeyDown = (event) => {
|
|
22
|
+
onKeyDown?.(event);
|
|
23
|
+
if (!disabled)
|
|
24
|
+
void sortableKeyDown(event.nativeEvent, event.currentTarget, commit);
|
|
25
|
+
};
|
|
26
|
+
return (_jsx(Tag, { ...rest, className: clsx(s.Sortable, className), "data-sortable": "", "data-layout": layout, "data-disabled": disabled ? "" : undefined, "data-handles": handles?.toString(), onPointerDown: handlePointerDown, onKeyDown: handleKeyDown, onDragStart: preventNativeDrag, children: children }));
|
|
27
|
+
}
|
|
28
|
+
/** The grip of an item. Arrow keys move the item while the handle has focus. */
|
|
29
|
+
function SortableHandle({ "aria-label": ariaLabel = "Reorder", className, children, ...rest }) {
|
|
30
|
+
return (_jsx("button", { ...rest, type: "button", className: clsx(s.Handle, className), "data-sortable-handle": "", "aria-label": ariaLabel, children: children ?? _jsx(GripVertical, { "aria-hidden": true }) }));
|
|
31
|
+
}
|
|
32
|
+
Sortable.Handle = SortableHandle;
|
|
33
|
+
//# sourceMappingURL=Sortable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Sortable.js","sourceRoot":"","sources":["../../../../src/components/Sortable/Sortable.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAErC,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,mBAAmB,EAAuB,MAAM,oBAAoB,CAAA;AACxG,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAEtC,OAAO,CAAC,MAAM,wDAAwD,CAAA;AAqCtE,MAAM,iBAAiB,GAAG,CAAC,KAAgB,EAAE,EAAE,CAAC,KAAK,CAAC,cAAc,EAAE,CAAA;AAEtE,8HAA8H;AAC9H,MAAM,UAAU,QAAQ,CAAI,EAC1B,KAAK,EACL,QAAQ,EACR,MAAM,GAAG,MAAM,EACf,EAAE,EAAE,GAAG,GAAG,KAAK,EACf,QAAQ,GAAG,KAAK,EAChB,OAAO,EACP,SAAS,EACT,QAAQ,EACR,aAAa,EACb,SAAS,EACT,GAAG,IAAI,EACU;IACjB,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAA;IAElD,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAU,EAAE,EAAE;QAC1C,SAAS,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAA;IACtF,CAAC,CAAA;IAED,MAAM,iBAAiB,GAAG,CAAC,KAAmC,EAAE,EAAE;QAChE,aAAa,EAAE,CAAC,KAAK,CAAC,CAAA;QACtB,IAAI,CAAC,QAAQ;YAAE,mBAAmB,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5F,CAAC,CAAA;IAED,MAAM,aAAa,GAAG,CAAC,KAAoC,EAAE,EAAE;QAC7D,SAAS,EAAE,CAAC,KAAK,CAAC,CAAA;QAClB,IAAI,CAAC,QAAQ;YAAE,KAAK,eAAe,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,aAAa,EAAE,MAAM,CAAC,CAAA;IACrF,CAAC,CAAA;IAED,OAAO,CACL,KAAC,GAAG,OACE,IAAI,EACR,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,mBACxB,EAAE,iBACH,MAAM,mBACJ,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,kBAC1B,OAAO,EAAE,QAAQ,EAAE,EACjC,aAAa,EAAE,iBAAiB,EAChC,SAAS,EAAE,aAAa,EACxB,WAAW,EAAE,iBAAiB,YAE7B,QAAQ,GACL,CACP,CAAA;AACH,CAAC;AAUD,gFAAgF;AAChF,SAAS,cAAc,CAAC,EAAE,YAAY,EAAE,SAAS,GAAG,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAuB;IAChH,OAAO,CACL,oBAAY,IAAI,EAAE,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,0BAAuB,EAAE,gBAAa,SAAS,YAChH,QAAQ,IAAI,KAAC,YAAY,0BAAe,GAClC,CACV,CAAA;AACH,CAAC;AAED,QAAQ,CAAC,MAAM,GAAG,cAAc,CAAA","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport type { ComponentProps, DragEvent, ElementType, KeyboardEvent, PointerEvent, ReactNode } from \"react\"\nimport { flushSync } from \"react-dom\"\n\nimport { useLatestValue } from \"../../hooks/useLatestValue\"\nimport { moveItem, sortableKeyDown, sortablePointerDown, type SortableLayout } from \"../../lib/sortable\"\nimport { GripVertical } from \"../Icon\"\n\nimport s from \"@plexui/styles/components/Sortable/Sortable.module.css\"\n\nexport type SortableProps<T> = {\n /**\n * The list, in the order of the children\n */\n value: readonly T[]\n /**\n * Called with the new order after a drop\n */\n onChange?: (value: T[]) => void\n /**\n * `list` for rows one under another, `grid` for items that stand side by side\n * @default list\n */\n layout?: SortableLayout\n /**\n * Element to render, such as `TableBody` for table rows\n * @default div\n */\n as?: ElementType\n /**\n * Turns dragging off\n * @default false\n */\n disabled?: boolean\n /**\n * Shows the grips of `Sortable.Handle`. A hidden grip still takes the keyboard, and the item drags from anywhere but a control.\n * @default true in a table, otherwise false\n */\n handles?: boolean\n /**\n * The items, one direct child per entry of `value`, keyed by the entry and not by its index\n */\n children?: ReactNode\n} & Omit<ComponentProps<\"div\">, \"children\" | \"onChange\">\n\nconst preventNativeDrag = (event: DragEvent) => event.preventDefault()\n\n/** Reorders its direct children by dragging, from anywhere but a control, or by a `Sortable.Handle` where grips are shown. */\nexport function Sortable<T>({\n value,\n onChange,\n layout = \"list\",\n as: Tag = \"div\",\n disabled = false,\n handles,\n className,\n children,\n onPointerDown,\n onKeyDown,\n ...rest\n}: SortableProps<T>) {\n const latest = useLatestValue({ value, onChange })\n\n const commit = (from: number, to: number) => {\n flushSync(() => latest.current.onChange?.(moveItem(latest.current.value, from, to)))\n }\n\n const handlePointerDown = (event: PointerEvent<HTMLDivElement>) => {\n onPointerDown?.(event)\n if (!disabled) sortablePointerDown(event.nativeEvent, event.currentTarget, layout, commit)\n }\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event)\n if (!disabled) void sortableKeyDown(event.nativeEvent, event.currentTarget, commit)\n }\n\n return (\n <Tag\n {...rest}\n className={clsx(s.Sortable, className)}\n data-sortable=\"\"\n data-layout={layout}\n data-disabled={disabled ? \"\" : undefined}\n data-handles={handles?.toString()}\n onPointerDown={handlePointerDown}\n onKeyDown={handleKeyDown}\n onDragStart={preventNativeDrag}\n >\n {children}\n </Tag>\n )\n}\n\nexport type SortableHandleProps = {\n /**\n * Name of the handle for assistive technology\n * @default Reorder\n */\n \"aria-label\"?: string\n} & ComponentProps<\"button\">\n\n/** The grip of an item. Arrow keys move the item while the handle has focus. */\nfunction SortableHandle({ \"aria-label\": ariaLabel = \"Reorder\", className, children, ...rest }: SortableHandleProps) {\n return (\n <button {...rest} type=\"button\" className={clsx(s.Handle, className)} data-sortable-handle=\"\" aria-label={ariaLabel}>\n {children ?? <GripVertical aria-hidden />}\n </button>\n )\n}\n\nSortable.Handle = SortableHandle\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/Sortable/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAgD,MAAM,YAAY,CAAA","sourcesContent":["export { Sortable, type SortableHandleProps, type SortableProps } from \"./Sortable\"\n"]}
|
|
@@ -141,16 +141,17 @@ const TabsRoot = ({ value, onChange, children, variant = "segmented", orientatio
|
|
|
141
141
|
});
|
|
142
142
|
});
|
|
143
143
|
}
|
|
144
|
+
else if (thumb.style.transition) {
|
|
145
|
+
// Normal update (value change, etc.): the thumb leaves with the label's colour
|
|
146
|
+
applyThumbSizing(true);
|
|
147
|
+
}
|
|
144
148
|
else {
|
|
145
|
-
//
|
|
149
|
+
// First measure: apply transition after initial calculation is set
|
|
146
150
|
waitForAnimationFrame(() => {
|
|
147
|
-
applyThumbSizing(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
thumb.style.transition = transitionProperty;
|
|
152
|
-
});
|
|
153
|
-
}
|
|
151
|
+
applyThumbSizing(false);
|
|
152
|
+
waitForAnimationFrame(() => {
|
|
153
|
+
thumb.style.transition = transitionProperty;
|
|
154
|
+
});
|
|
154
155
|
});
|
|
155
156
|
}
|
|
156
157
|
}, [applyThumbSizing, value, size, gutterSize, pill, flush, transitionProperty]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tabs.js","sourceRoot":"","sources":["../../../../src/components/Tabs/Tabs.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { ToggleGroup } from \"radix-ui\"\nimport {\n Children,\n cloneElement,\n Fragment,\n isValidElement,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type ReactElement,\n type ReactNode,\n} from \"react\"\nimport { useResizeObserver } from \"usehooks-ts\"\nimport { handlePressableMouseEnter, waitForAnimationFrame } from \"../../lib/helpers\"\nimport { type ControlSize, type SemanticColors, type Sizes, type Variants } from \"../../types\"\nimport { ChevronDownMd } from \"../Icon\"\nimport { LoadingIndicator } from \"../Indicator\"\nimport { Menu } from \"../Menu\"\nimport { fitCount, visibleTabCount } from \"./overflow\"\nimport s from \"@plexui/styles/components/Tabs/Tabs.module.css\"\n\nexport type SizeVariant = \"2xs\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"\n\nexport type TabsVariant = \"segmented\" | \"underline\"\nexport type TabsOrientation = \"horizontal\" | \"vertical\"\n\nexport type TabsProps<T extends string> = {\n /**\n * Controlled value for the group\n */\n \"value\": T\n /** Callback for when a new value is selected */\n \"onChange\"?: (nextValue: T) => void\n /** Callback any time the control is clicked (even if a new value was not selected) */\n \"onClick\"?: () => void\n /**\n * Text read aloud to screen readers when the control is focused\n */\n \"aria-label\": string\n /**\n * Visual variant of the tab group\n * - `\"segmented\"` — background container with sliding highlight (default)\n * - `\"underline\"` — no background, animated line indicator under active tab\n * @default \"segmented\"\n */\n \"variant\"?: TabsVariant\n /**\n * Orientation of the tab layout\n * @default \"horizontal\"\n */\n \"orientation\"?: TabsOrientation\n /**\n * Controls the size of the tabs\n *\n * | 3xs | 2xs | xs | sm | md | lg | xl | 2xl | 3xl |\n * | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- |\n * | `22px` | `24px` | `26px` | `28px` | `32px` | `36px` | `40px` | `44px` | `48px` |\n *\n * @default md\n */\n \"size\"?: ControlSize\n /**\n * Controls gutter on the edges of the button, defaults to value from `size`.\n *\n * | 2xs | xs | sm | md | lg | xl |\n * | ------ | ------ | ------ | ------ | ------ | ------ |\n * | `6px` | `8px` | `10px` | `12px` | `14px` | `16px` |\n */\n \"gutterSize\"?: Sizes<\"2xs\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\">\n /** Disable the entire group */\n \"disabled\"?: boolean\n /**\n * Display the control as a block element with equal width segments\n * @default false\n */\n \"block\"?: boolean\n /**\n * Determines if the tabs should be a fully rounded pill shape.\n * Only applies to the `\"segmented\"` variant.\n * @default true\n */\n \"pill\"?: boolean\n /**\n * Flush underline style — removes tab padding so the indicator\n * matches the text width exactly, uses gap for spacing, and\n * removes the bottom border.\n * Only applies to the `\"underline\"` variant.\n * @default false\n */\n \"flush\"?: boolean\n /**\n * What happens to tabs that do not fit in one row: the strip scrolls\n * sideways (`scroll`), or the tabs that do not fit move into a menu at the\n * end of the strip (`menu`). The menu button shows the active tab's name\n * when it is one of the hidden ones. Horizontal tabs without `block` only.\n * @default \"scroll\"\n */\n \"overflow\"?: \"scroll\" | \"menu\"\n /**\n * Text of the menu button with `overflow=\"menu\"`\n * @default \"More\"\n */\n \"overflowLabel\"?: string\n \"className\"?: string\n \"children\": React.ReactNode\n}\n\nexport const Tabs = <T extends string>({ overflow = \"scroll\", overflowLabel = \"More\", ...props }: TabsProps<T>) => {\n if (overflow === \"menu\" && !props.block && props.orientation !== \"vertical\") {\n return <OverflowTabs {...props} overflowLabel={overflowLabel} />\n }\n return <TabsRoot {...props} />\n}\n\nconst TabsRoot = <T extends string>({\n value,\n onChange,\n children,\n variant = \"segmented\",\n orientation = \"horizontal\",\n block,\n pill = true,\n flush,\n size = \"md\",\n gutterSize,\n className,\n onClick,\n ...restProps\n}: Omit<TabsProps<T>, \"overflow\" | \"overflowLabel\">) => {\n const rootRef = useRef<HTMLDivElement>(null)\n const thumbRef = useRef<HTMLDivElement>(null)\n const prevSizeRef = useRef(size)\n const isVertical = orientation === \"vertical\"\n\n const applyThumbSizing = useCallback(\n (attemptScroll: boolean) => {\n const root = rootRef.current\n const thumb = thumbRef.current\n\n if (!root || !thumb) {\n return\n }\n\n // Get selected node\n const activeNode = root?.querySelector<HTMLDivElement>('[data-state=\"on\"]')\n\n // Impossible\n if (!activeNode) {\n return\n }\n\n if (isVertical) {\n const rootHeight = root.clientHeight\n let targetHeight = Math.floor(activeNode.clientHeight)\n const targetOffset = activeNode.offsetTop\n\n // Detect subpixel edge case\n if (rootHeight - (targetHeight + targetOffset) < 2) {\n targetHeight = targetHeight - 1\n }\n\n thumb.style.height = `${Math.floor(targetHeight)}px`\n thumb.style.width = \"\"\n thumb.style.transform = `translateY(${targetOffset}px)`\n\n // Scroll into view if needed\n if (root.scrollHeight > rootHeight) {\n const buffer = rootHeight * 0.15\n const scrollTop = root.scrollTop\n const top = activeNode.offsetTop\n const bottom = top + targetHeight\n if (top < scrollTop + buffer || bottom > scrollTop + rootHeight - buffer) {\n if (attemptScroll) {\n activeNode.scrollIntoView({ block: \"center\", inline: \"nearest\", behavior: \"smooth\" })\n }\n }\n }\n } else {\n const rootWidth = root.clientWidth\n let targetWidth = Math.floor(activeNode.clientWidth)\n const targetOffset = activeNode.offsetLeft\n\n // Detect if the thumb is moving too far to the edge of the container.\n // This would most commonly be due to subpixel widths adding up to excessive distance.\n if (rootWidth - (targetWidth + targetOffset) < 2) {\n targetWidth = targetWidth - 1\n }\n\n thumb.style.width = `${Math.floor(targetWidth)}px`\n thumb.style.height = \"\"\n thumb.style.transform = `translateX(${targetOffset}px)`\n\n // If the control is scrollable, ensure the active option is visible\n if (root.scrollWidth > rootWidth) {\n // Only scroll items near the edge, but not the inner 2/3.\n const buffer = rootWidth * 0.15\n const scrollLeft = root.scrollLeft\n const left = activeNode.offsetLeft\n const right = left + targetWidth\n if (left < scrollLeft + buffer || right > scrollLeft + rootWidth - buffer) {\n // Cheap trick to avoid unintentional scroll on mount - transition is set after mounting\n if (attemptScroll) {\n activeNode.scrollIntoView({ block: \"nearest\", inline: \"center\", behavior: \"smooth\" })\n }\n }\n }\n }\n },\n [isVertical],\n )\n\n useResizeObserver({\n // @ts-expect-error(2322) -- bug in types: https://github.com/juliencrn/usehooks-ts/issues/663\n ref: rootRef,\n onResize: () => {\n const thumb = thumbRef.current\n\n if (!thumb) {\n return\n }\n\n // Perform the size update instantly\n const currentTransition = thumb.style.transition\n thumb.style.transition = \"\"\n applyThumbSizing(false)\n thumb.style.transition = currentTransition\n },\n })\n\n // Tabs added, removed, reordered or relabelled move the active tab without\n // resizing the group: measure again, instantly, like a resize\n useEffect(() => {\n const root = rootRef.current\n if (!root || typeof MutationObserver === \"undefined\") return\n const observer = new MutationObserver(() => {\n const thumb = thumbRef.current\n if (!thumb) return\n const currentTransition = thumb.style.transition\n thumb.style.transition = \"\"\n applyThumbSizing(false)\n thumb.style.transition = currentTransition\n })\n observer.observe(root, { childList: true, characterData: true, subtree: true })\n return () => observer.disconnect()\n }, [applyThumbSizing])\n\n const transitionProperty = isVertical\n ? \"height 200ms var(--cubic-enter), transform 200ms var(--cubic-enter)\"\n : \"width 200ms var(--cubic-enter), transform 200ms var(--cubic-enter)\"\n\n useLayoutEffect(() => {\n const root = rootRef.current\n const thumb = thumbRef.current\n\n if (!root || !thumb) {\n return\n }\n\n const sizeChanged = prevSizeRef.current !== size\n prevSizeRef.current = size\n\n if (sizeChanged) {\n // Size changed - disable transition, wait for CSS, then apply sizing\n const currentTransition = thumb.style.transition\n thumb.style.transition = \"\"\n\n waitForAnimationFrame(() => {\n applyThumbSizing(false)\n waitForAnimationFrame(() => {\n thumb.style.transition = currentTransition\n })\n })\n } else {\n // Normal update (value change, etc.)\n waitForAnimationFrame(() => {\n applyThumbSizing(!!thumb.style.transition)\n\n // Apply transition after initial calculation is set\n if (!thumb.style.transition) {\n waitForAnimationFrame(() => {\n thumb.style.transition = transitionProperty\n })\n }\n })\n }\n }, [applyThumbSizing, value, size, gutterSize, pill, flush, transitionProperty])\n\n const handleValueChange = (nextValue: T) => {\n // Only trigger onChange when a value exists\n // Disallow toggling off enabled items\n if (nextValue && onChange) onChange(nextValue)\n }\n\n // Only apply pill for segmented variant\n const isPill = variant === \"segmented\" && pill\n // Only apply flush for underline variant\n const isFlush = variant === \"underline\" && flush\n\n return (\n <ToggleGroup.Root\n ref={rootRef}\n className={clsx(s.Tabs, className)}\n type=\"single\"\n value={value}\n loop={false}\n onValueChange={handleValueChange}\n onClick={onClick}\n data-variant={variant}\n data-orientation={orientation}\n data-block={block ? \"\" : undefined}\n data-pill={isPill ? \"\" : undefined}\n data-flush={isFlush ? \"\" : undefined}\n data-size={size}\n data-gutter-size={gutterSize}\n {...restProps}\n >\n <div className={s.TabsThumb} ref={thumbRef} />\n {children}\n </ToggleGroup.Root>\n )\n}\n\n/**\n * Badge configuration for Tabs.Tab\n */\nexport type TabsBadgeProp =\n | React.ReactNode\n | {\n content: React.ReactNode\n color?: SemanticColors<\n \"secondary\" | \"success\" | \"danger\" | \"warning\" | \"info\" | \"discovery\" | \"caution\"\n >\n variant?: Variants<\"soft\" | \"solid\">\n pill?: boolean\n loading?: boolean\n }\n\nexport type TabProps = {\n /**\n * Tab value\n */\n \"value\": string\n /**\n * Text read aloud to screen readers when the tab is focused\n */\n \"aria-label\"?: string\n /**\n * Text content to render in the tab\n */\n \"children\"?: React.ReactNode\n /**\n * Icon to render before the text content\n */\n \"icon\"?: React.ReactNode\n /**\n * Badge to render after the text content.\n * Can be a simple value or an object with content, color, variant, and loading options.\n * @example badge={5}\n * @example badge={{ content: 5, color: \"danger\" }}\n */\n \"badge\"?: TabsBadgeProp\n /**\n * Disable the individual tab\n */\n \"disabled\"?: boolean\n}\n\n// Type guard for badge object form\nconst isBadgeObject = (\n badge: TabsBadgeProp,\n): badge is Exclude<TabsBadgeProp, React.ReactNode> & { content: React.ReactNode } => {\n return badge != null && typeof badge === \"object\" && \"content\" in badge\n}\n\nconst Tab = ({ children, icon, badge, ...restProps }: TabProps) => {\n // Normalize badge prop\n const badgeProps = badge != null ? (isBadgeObject(badge) ? badge : { content: badge }) : null\n\n return (\n <ToggleGroup.Item\n className={s.Tab}\n {...restProps}\n onPointerEnter={handlePressableMouseEnter}\n >\n <span className={s.TabContent}>\n {icon}\n {children && <span>{children}</span>}\n {badgeProps && (\n <span\n className={s.TabBadge}\n data-color={badgeProps.color ?? \"secondary\"}\n data-variant={badgeProps.variant ?? \"soft\"}\n data-pill={badgeProps.pill ? \"\" : undefined}\n >\n {badgeProps.loading ? <LoadingIndicator /> : badgeProps.content}\n </span>\n )}\n </span>\n </ToggleGroup.Item>\n )\n}\n\n// =============================================\n// overflow=\"menu\"\n// =============================================\n\n/** Value of the menu button; no real tab has it */\nconst MORE_VALUE = \"__plexui_tabs_more__\"\n\ntype TabElement = ReactElement<TabProps>\n\n/** The tabs among the children, through fragments */\nconst tabElements = (children: ReactNode): TabElement[] =>\n Children.toArray(children).flatMap((child) => {\n if (!isValidElement<{ children?: ReactNode }>(child)) return []\n return child.type === Fragment ? tabElements(child.props.children) : [child as TabElement]\n })\n\nconst plainText = (node: unknown): string => {\n if (typeof node === \"string\" || typeof node === \"number\") return String(node)\n if (Array.isArray(node)) return node.map(plainText).join(\"\")\n if (isValidElement<{ children?: ReactNode }>(node)) return plainText(node.props.children)\n return \"\"\n}\n\nconst badgeText = (badge: TabsBadgeProp | undefined) =>\n badge != null && isBadgeObject(badge) ? plainText(badge.content) : plainText(badge)\n\n/** A tab's name: its text, else its accessible name, else its value */\nconst tabLabel = (item: TabElement) => plainText(item.props.children) || item.props[\"aria-label\"] || item.props.value\n\n/** What a tab's width depends on: the strip measures again when it changes */\nconst tabsSignature = (items: TabElement[]) =>\n items\n .map((item) =>\n [item.props.value, plainText(item.props.children), badgeText(item.props.badge), item.props.icon != null].join(\"\\u0000\"),\n )\n .join(\"\\u0001\")\n\n/**\n * `Menu.Trigger` sets `data-state` (open or closed) on its child, while a tab\n * keeps `on` or `off` in the same attribute and the thumb finds the active tab\n * by it. The menu's value does not reach the tab; its handlers and\n * `aria-haspopup` / `aria-expanded` do.\n */\nconst MoreTab = ({ \"data-state\": _menuState, ...restProps }: TabProps & { \"data-state\"?: string }) => (\n <Tab {...restProps} />\n)\n\nconst OverflowTabs = <T extends string>({\n children,\n value,\n onChange,\n overflowLabel,\n ...restProps\n}: Omit<TabsProps<T>, \"overflow\"> & { overflowLabel: string }) => {\n const items = tabElements(children)\n // The strip's own props size the tabs and the menu button too\n const { size, variant, gutterSize, pill, flush } = restProps\n const signature = [overflowLabel, size, variant, gutterSize, pill, flush, tabsSignature(items)].join(\"\\u0002\")\n const activeIndex = items.findIndex((item) => item.props.value === value)\n\n // null while the measuring pass renders every tab and the menu button\n const [visibleCount, setVisibleCount] = useState<number | null>(null)\n const [known, setKnown] = useState({ signature, activeIndex })\n const hostRef = useRef<HTMLDivElement>(null)\n const measuringRef = useRef(true)\n const boxWidthRef = useRef(-1)\n\n // New tabs measure again. A new active tab measures again when it moves\n // under the menu button or back out: the button carries the hidden one's name\n if (known.signature !== signature || known.activeIndex !== activeIndex) {\n const crossed =\n visibleCount !== null && (known.activeIndex >= visibleCount || activeIndex >= visibleCount)\n setKnown({ signature, activeIndex })\n if (visibleCount !== null && (known.signature !== signature || crossed)) setVisibleCount(null)\n }\n\n useLayoutEffect(() => {\n measuringRef.current = visibleCount === null\n }, [visibleCount])\n\n useLayoutEffect(() => {\n if (visibleCount !== null) return\n const root = hostRef.current?.firstElementChild\n if (!(root instanceof HTMLElement)) return\n\n // The measuring pass renders every tab, then the menu button\n const buttons = Array.from(root.querySelectorAll<HTMLElement>(\":scope > button\"))\n if (buttons.length !== items.length + 1) return\n\n const widths = buttons.map((button) => button.getBoundingClientRect().width)\n const moreButton = buttons[buttons.length - 1]\n const moreWidth = widths.pop() ?? 0\n const style = getComputedStyle(root)\n const available =\n root.getBoundingClientRect().width -\n (Number.parseFloat(style.paddingLeft) || 0) -\n (Number.parseFloat(style.paddingRight) || 0)\n const gap = Number.parseFloat(style.columnGap) || 0\n boxWidthRef.current = hostRef.current?.parentElement?.clientWidth ?? -1\n\n // A hidden strip has no width to decide by: show every tab, and measure\n // when it appears (the observer sees the width change)\n if (available <= 0) {\n setVisibleCount(items.length)\n return\n }\n\n // The button with the active tab's name: that tab's width plus the chevron\n const chevron = moreButton?.querySelector(\"svg\")\n const chevronWidth = chevron?.getBoundingClientRect().width ?? 0\n const labelGap = chevron?.parentElement ? Number.parseFloat(getComputedStyle(chevron.parentElement).columnGap) || 0 : 0\n const activeWidth = activeIndex < 0 ? 0 : (widths[activeIndex] ?? 0) + chevronWidth + labelGap\n\n setVisibleCount(visibleTabCount(widths, moreWidth, activeWidth, activeIndex, gap, available))\n }, [visibleCount, items.length, activeIndex])\n\n // The width to fit is the container's, not the strip's: the strip shrinks\n // to its content. Reports during a measuring pass are skipped, since the\n // full strip may be pushing its container wider\n useEffect(() => {\n const box = hostRef.current?.parentElement\n if (!box || typeof ResizeObserver === \"undefined\") return\n const observer = new ResizeObserver(() => {\n if (measuringRef.current) return\n const width = box.clientWidth\n if (width === boxWidthRef.current) return\n boxWidthRef.current = width\n setVisibleCount(null)\n })\n observer.observe(box)\n return () => observer.disconnect()\n }, [])\n\n const measuring = visibleCount === null\n const shown = measuring ? items : items.slice(0, visibleCount)\n const hidden = measuring ? [] : items.slice(visibleCount)\n const hiddenActive = hidden.find((item) => item.props.value === value) ?? null\n\n return (\n <div ref={hostRef} className={s.OverflowHost}>\n <Menu>\n <TabsRoot<string>\n {...restProps}\n data-overflow=\"menu\"\n value={hiddenActive ? MORE_VALUE : value}\n onChange={(next) => {\n // Pressing the menu button opens the menu; it is not a tab\n if (next !== MORE_VALUE) onChange?.(next as T)\n }}\n >\n {/* Keyed by value: tabs from different fragments may share a key */}\n {shown.map((item) => cloneElement(item, { key: item.props.value }))}\n {(measuring || hidden.length > 0) && (\n <Menu.Trigger>\n <MoreTab value={MORE_VALUE}>\n <span className={s.OverflowLabel}>\n {hiddenActive ? tabLabel(hiddenActive) : overflowLabel}\n <ChevronDownMd />\n </span>\n </MoreTab>\n </Menu.Trigger>\n )}\n </TabsRoot>\n <Menu.Content align=\"end\" minWidth=\"auto\">\n <Menu.RadioGroup<string> value={value} onChange={(next) => onChange?.(next as T)}>\n {hidden.map((item) => {\n const count = badgeText(item.props.badge)\n return (\n <Menu.RadioItem<string>\n key={item.props.value}\n value={item.props.value}\n disabled={restProps.disabled || item.props.disabled}\n >\n {item.props.icon}\n {item.props.children ?? item.props[\"aria-label\"] ?? item.props.value}\n {/* A tab's count moves into the menu with it */}\n {count !== \"\" && <span className={s.OverflowBadge}>{count}</span>}\n </Menu.RadioItem>\n )\n })}\n </Menu.RadioGroup>\n </Menu.Content>\n </Menu>\n </div>\n )\n}\n\n// Attach sub-components\nTabs.Tab = Tab\n// Backward-compat alias\nTabs.Option = Tab\n"]}
|
|
1
|
+
{"version":3,"file":"Tabs.js","sourceRoot":"","sources":["../../../../src/components/Tabs/Tabs.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { ToggleGroup } from \"radix-ui\"\nimport {\n Children,\n cloneElement,\n Fragment,\n isValidElement,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type ReactElement,\n type ReactNode,\n} from \"react\"\nimport { useResizeObserver } from \"usehooks-ts\"\nimport { handlePressableMouseEnter, waitForAnimationFrame } from \"../../lib/helpers\"\nimport { type ControlSize, type SemanticColors, type Sizes, type Variants } from \"../../types\"\nimport { ChevronDownMd } from \"../Icon\"\nimport { LoadingIndicator } from \"../Indicator\"\nimport { Menu } from \"../Menu\"\nimport { fitCount, visibleTabCount } from \"./overflow\"\nimport s from \"@plexui/styles/components/Tabs/Tabs.module.css\"\n\nexport type SizeVariant = \"2xs\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"\n\nexport type TabsVariant = \"segmented\" | \"underline\"\nexport type TabsOrientation = \"horizontal\" | \"vertical\"\n\nexport type TabsProps<T extends string> = {\n /**\n * Controlled value for the group\n */\n \"value\": T\n /** Callback for when a new value is selected */\n \"onChange\"?: (nextValue: T) => void\n /** Callback any time the control is clicked (even if a new value was not selected) */\n \"onClick\"?: () => void\n /**\n * Text read aloud to screen readers when the control is focused\n */\n \"aria-label\": string\n /**\n * Visual variant of the tab group\n * - `\"segmented\"` — background container with sliding highlight (default)\n * - `\"underline\"` — no background, animated line indicator under active tab\n * @default \"segmented\"\n */\n \"variant\"?: TabsVariant\n /**\n * Orientation of the tab layout\n * @default \"horizontal\"\n */\n \"orientation\"?: TabsOrientation\n /**\n * Controls the size of the tabs\n *\n * | 3xs | 2xs | xs | sm | md | lg | xl | 2xl | 3xl |\n * | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- |\n * | `22px` | `24px` | `26px` | `28px` | `32px` | `36px` | `40px` | `44px` | `48px` |\n *\n * @default md\n */\n \"size\"?: ControlSize\n /**\n * Controls gutter on the edges of the button, defaults to value from `size`.\n *\n * | 2xs | xs | sm | md | lg | xl |\n * | ------ | ------ | ------ | ------ | ------ | ------ |\n * | `6px` | `8px` | `10px` | `12px` | `14px` | `16px` |\n */\n \"gutterSize\"?: Sizes<\"2xs\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\">\n /** Disable the entire group */\n \"disabled\"?: boolean\n /**\n * Display the control as a block element with equal width segments\n * @default false\n */\n \"block\"?: boolean\n /**\n * Determines if the tabs should be a fully rounded pill shape.\n * Only applies to the `\"segmented\"` variant.\n * @default true\n */\n \"pill\"?: boolean\n /**\n * Flush underline style — removes tab padding so the indicator\n * matches the text width exactly, uses gap for spacing, and\n * removes the bottom border.\n * Only applies to the `\"underline\"` variant.\n * @default false\n */\n \"flush\"?: boolean\n /**\n * What happens to tabs that do not fit in one row: the strip scrolls\n * sideways (`scroll`), or the tabs that do not fit move into a menu at the\n * end of the strip (`menu`). The menu button shows the active tab's name\n * when it is one of the hidden ones. Horizontal tabs without `block` only.\n * @default \"scroll\"\n */\n \"overflow\"?: \"scroll\" | \"menu\"\n /**\n * Text of the menu button with `overflow=\"menu\"`\n * @default \"More\"\n */\n \"overflowLabel\"?: string\n \"className\"?: string\n \"children\": React.ReactNode\n}\n\nexport const Tabs = <T extends string>({ overflow = \"scroll\", overflowLabel = \"More\", ...props }: TabsProps<T>) => {\n if (overflow === \"menu\" && !props.block && props.orientation !== \"vertical\") {\n return <OverflowTabs {...props} overflowLabel={overflowLabel} />\n }\n return <TabsRoot {...props} />\n}\n\nconst TabsRoot = <T extends string>({\n value,\n onChange,\n children,\n variant = \"segmented\",\n orientation = \"horizontal\",\n block,\n pill = true,\n flush,\n size = \"md\",\n gutterSize,\n className,\n onClick,\n ...restProps\n}: Omit<TabsProps<T>, \"overflow\" | \"overflowLabel\">) => {\n const rootRef = useRef<HTMLDivElement>(null)\n const thumbRef = useRef<HTMLDivElement>(null)\n const prevSizeRef = useRef(size)\n const isVertical = orientation === \"vertical\"\n\n const applyThumbSizing = useCallback(\n (attemptScroll: boolean) => {\n const root = rootRef.current\n const thumb = thumbRef.current\n\n if (!root || !thumb) {\n return\n }\n\n // Get selected node\n const activeNode = root?.querySelector<HTMLDivElement>('[data-state=\"on\"]')\n\n // Impossible\n if (!activeNode) {\n return\n }\n\n if (isVertical) {\n const rootHeight = root.clientHeight\n let targetHeight = Math.floor(activeNode.clientHeight)\n const targetOffset = activeNode.offsetTop\n\n // Detect subpixel edge case\n if (rootHeight - (targetHeight + targetOffset) < 2) {\n targetHeight = targetHeight - 1\n }\n\n thumb.style.height = `${Math.floor(targetHeight)}px`\n thumb.style.width = \"\"\n thumb.style.transform = `translateY(${targetOffset}px)`\n\n // Scroll into view if needed\n if (root.scrollHeight > rootHeight) {\n const buffer = rootHeight * 0.15\n const scrollTop = root.scrollTop\n const top = activeNode.offsetTop\n const bottom = top + targetHeight\n if (top < scrollTop + buffer || bottom > scrollTop + rootHeight - buffer) {\n if (attemptScroll) {\n activeNode.scrollIntoView({ block: \"center\", inline: \"nearest\", behavior: \"smooth\" })\n }\n }\n }\n } else {\n const rootWidth = root.clientWidth\n let targetWidth = Math.floor(activeNode.clientWidth)\n const targetOffset = activeNode.offsetLeft\n\n // Detect if the thumb is moving too far to the edge of the container.\n // This would most commonly be due to subpixel widths adding up to excessive distance.\n if (rootWidth - (targetWidth + targetOffset) < 2) {\n targetWidth = targetWidth - 1\n }\n\n thumb.style.width = `${Math.floor(targetWidth)}px`\n thumb.style.height = \"\"\n thumb.style.transform = `translateX(${targetOffset}px)`\n\n // If the control is scrollable, ensure the active option is visible\n if (root.scrollWidth > rootWidth) {\n // Only scroll items near the edge, but not the inner 2/3.\n const buffer = rootWidth * 0.15\n const scrollLeft = root.scrollLeft\n const left = activeNode.offsetLeft\n const right = left + targetWidth\n if (left < scrollLeft + buffer || right > scrollLeft + rootWidth - buffer) {\n // Cheap trick to avoid unintentional scroll on mount - transition is set after mounting\n if (attemptScroll) {\n activeNode.scrollIntoView({ block: \"nearest\", inline: \"center\", behavior: \"smooth\" })\n }\n }\n }\n }\n },\n [isVertical],\n )\n\n useResizeObserver({\n // @ts-expect-error(2322) -- bug in types: https://github.com/juliencrn/usehooks-ts/issues/663\n ref: rootRef,\n onResize: () => {\n const thumb = thumbRef.current\n\n if (!thumb) {\n return\n }\n\n // Perform the size update instantly\n const currentTransition = thumb.style.transition\n thumb.style.transition = \"\"\n applyThumbSizing(false)\n thumb.style.transition = currentTransition\n },\n })\n\n // Tabs added, removed, reordered or relabelled move the active tab without\n // resizing the group: measure again, instantly, like a resize\n useEffect(() => {\n const root = rootRef.current\n if (!root || typeof MutationObserver === \"undefined\") return\n const observer = new MutationObserver(() => {\n const thumb = thumbRef.current\n if (!thumb) return\n const currentTransition = thumb.style.transition\n thumb.style.transition = \"\"\n applyThumbSizing(false)\n thumb.style.transition = currentTransition\n })\n observer.observe(root, { childList: true, characterData: true, subtree: true })\n return () => observer.disconnect()\n }, [applyThumbSizing])\n\n const transitionProperty = isVertical\n ? \"height 200ms var(--cubic-enter), transform 200ms var(--cubic-enter)\"\n : \"width 200ms var(--cubic-enter), transform 200ms var(--cubic-enter)\"\n\n useLayoutEffect(() => {\n const root = rootRef.current\n const thumb = thumbRef.current\n\n if (!root || !thumb) {\n return\n }\n\n const sizeChanged = prevSizeRef.current !== size\n prevSizeRef.current = size\n\n if (sizeChanged) {\n // Size changed - disable transition, wait for CSS, then apply sizing\n const currentTransition = thumb.style.transition\n thumb.style.transition = \"\"\n\n waitForAnimationFrame(() => {\n applyThumbSizing(false)\n waitForAnimationFrame(() => {\n thumb.style.transition = currentTransition\n })\n })\n } else if (thumb.style.transition) {\n // Normal update (value change, etc.): the thumb leaves with the label's colour\n applyThumbSizing(true)\n } else {\n // First measure: apply transition after initial calculation is set\n waitForAnimationFrame(() => {\n applyThumbSizing(false)\n waitForAnimationFrame(() => {\n thumb.style.transition = transitionProperty\n })\n })\n }\n }, [applyThumbSizing, value, size, gutterSize, pill, flush, transitionProperty])\n\n const handleValueChange = (nextValue: T) => {\n // Only trigger onChange when a value exists\n // Disallow toggling off enabled items\n if (nextValue && onChange) onChange(nextValue)\n }\n\n // Only apply pill for segmented variant\n const isPill = variant === \"segmented\" && pill\n // Only apply flush for underline variant\n const isFlush = variant === \"underline\" && flush\n\n return (\n <ToggleGroup.Root\n ref={rootRef}\n className={clsx(s.Tabs, className)}\n type=\"single\"\n value={value}\n loop={false}\n onValueChange={handleValueChange}\n onClick={onClick}\n data-variant={variant}\n data-orientation={orientation}\n data-block={block ? \"\" : undefined}\n data-pill={isPill ? \"\" : undefined}\n data-flush={isFlush ? \"\" : undefined}\n data-size={size}\n data-gutter-size={gutterSize}\n {...restProps}\n >\n <div className={s.TabsThumb} ref={thumbRef} />\n {children}\n </ToggleGroup.Root>\n )\n}\n\n/**\n * Badge configuration for Tabs.Tab\n */\nexport type TabsBadgeProp =\n | React.ReactNode\n | {\n content: React.ReactNode\n color?: SemanticColors<\n \"secondary\" | \"success\" | \"danger\" | \"warning\" | \"info\" | \"discovery\" | \"caution\"\n >\n variant?: Variants<\"soft\" | \"solid\">\n pill?: boolean\n loading?: boolean\n }\n\nexport type TabProps = {\n /**\n * Tab value\n */\n \"value\": string\n /**\n * Text read aloud to screen readers when the tab is focused\n */\n \"aria-label\"?: string\n /**\n * Text content to render in the tab\n */\n \"children\"?: React.ReactNode\n /**\n * Icon to render before the text content\n */\n \"icon\"?: React.ReactNode\n /**\n * Badge to render after the text content.\n * Can be a simple value or an object with content, color, variant, and loading options.\n * @example badge={5}\n * @example badge={{ content: 5, color: \"danger\" }}\n */\n \"badge\"?: TabsBadgeProp\n /**\n * Disable the individual tab\n */\n \"disabled\"?: boolean\n}\n\n// Type guard for badge object form\nconst isBadgeObject = (\n badge: TabsBadgeProp,\n): badge is Exclude<TabsBadgeProp, React.ReactNode> & { content: React.ReactNode } => {\n return badge != null && typeof badge === \"object\" && \"content\" in badge\n}\n\nconst Tab = ({ children, icon, badge, ...restProps }: TabProps) => {\n // Normalize badge prop\n const badgeProps = badge != null ? (isBadgeObject(badge) ? badge : { content: badge }) : null\n\n return (\n <ToggleGroup.Item\n className={s.Tab}\n {...restProps}\n onPointerEnter={handlePressableMouseEnter}\n >\n <span className={s.TabContent}>\n {icon}\n {children && <span>{children}</span>}\n {badgeProps && (\n <span\n className={s.TabBadge}\n data-color={badgeProps.color ?? \"secondary\"}\n data-variant={badgeProps.variant ?? \"soft\"}\n data-pill={badgeProps.pill ? \"\" : undefined}\n >\n {badgeProps.loading ? <LoadingIndicator /> : badgeProps.content}\n </span>\n )}\n </span>\n </ToggleGroup.Item>\n )\n}\n\n// =============================================\n// overflow=\"menu\"\n// =============================================\n\n/** Value of the menu button; no real tab has it */\nconst MORE_VALUE = \"__plexui_tabs_more__\"\n\ntype TabElement = ReactElement<TabProps>\n\n/** The tabs among the children, through fragments */\nconst tabElements = (children: ReactNode): TabElement[] =>\n Children.toArray(children).flatMap((child) => {\n if (!isValidElement<{ children?: ReactNode }>(child)) return []\n return child.type === Fragment ? tabElements(child.props.children) : [child as TabElement]\n })\n\nconst plainText = (node: unknown): string => {\n if (typeof node === \"string\" || typeof node === \"number\") return String(node)\n if (Array.isArray(node)) return node.map(plainText).join(\"\")\n if (isValidElement<{ children?: ReactNode }>(node)) return plainText(node.props.children)\n return \"\"\n}\n\nconst badgeText = (badge: TabsBadgeProp | undefined) =>\n badge != null && isBadgeObject(badge) ? plainText(badge.content) : plainText(badge)\n\n/** A tab's name: its text, else its accessible name, else its value */\nconst tabLabel = (item: TabElement) => plainText(item.props.children) || item.props[\"aria-label\"] || item.props.value\n\n/** What a tab's width depends on: the strip measures again when it changes */\nconst tabsSignature = (items: TabElement[]) =>\n items\n .map((item) =>\n [item.props.value, plainText(item.props.children), badgeText(item.props.badge), item.props.icon != null].join(\"\\u0000\"),\n )\n .join(\"\\u0001\")\n\n/**\n * `Menu.Trigger` sets `data-state` (open or closed) on its child, while a tab\n * keeps `on` or `off` in the same attribute and the thumb finds the active tab\n * by it. The menu's value does not reach the tab; its handlers and\n * `aria-haspopup` / `aria-expanded` do.\n */\nconst MoreTab = ({ \"data-state\": _menuState, ...restProps }: TabProps & { \"data-state\"?: string }) => (\n <Tab {...restProps} />\n)\n\nconst OverflowTabs = <T extends string>({\n children,\n value,\n onChange,\n overflowLabel,\n ...restProps\n}: Omit<TabsProps<T>, \"overflow\"> & { overflowLabel: string }) => {\n const items = tabElements(children)\n // The strip's own props size the tabs and the menu button too\n const { size, variant, gutterSize, pill, flush } = restProps\n const signature = [overflowLabel, size, variant, gutterSize, pill, flush, tabsSignature(items)].join(\"\\u0002\")\n const activeIndex = items.findIndex((item) => item.props.value === value)\n\n // null while the measuring pass renders every tab and the menu button\n const [visibleCount, setVisibleCount] = useState<number | null>(null)\n const [known, setKnown] = useState({ signature, activeIndex })\n const hostRef = useRef<HTMLDivElement>(null)\n const measuringRef = useRef(true)\n const boxWidthRef = useRef(-1)\n\n // New tabs measure again. A new active tab measures again when it moves\n // under the menu button or back out: the button carries the hidden one's name\n if (known.signature !== signature || known.activeIndex !== activeIndex) {\n const crossed =\n visibleCount !== null && (known.activeIndex >= visibleCount || activeIndex >= visibleCount)\n setKnown({ signature, activeIndex })\n if (visibleCount !== null && (known.signature !== signature || crossed)) setVisibleCount(null)\n }\n\n useLayoutEffect(() => {\n measuringRef.current = visibleCount === null\n }, [visibleCount])\n\n useLayoutEffect(() => {\n if (visibleCount !== null) return\n const root = hostRef.current?.firstElementChild\n if (!(root instanceof HTMLElement)) return\n\n // The measuring pass renders every tab, then the menu button\n const buttons = Array.from(root.querySelectorAll<HTMLElement>(\":scope > button\"))\n if (buttons.length !== items.length + 1) return\n\n const widths = buttons.map((button) => button.getBoundingClientRect().width)\n const moreButton = buttons[buttons.length - 1]\n const moreWidth = widths.pop() ?? 0\n const style = getComputedStyle(root)\n const available =\n root.getBoundingClientRect().width -\n (Number.parseFloat(style.paddingLeft) || 0) -\n (Number.parseFloat(style.paddingRight) || 0)\n const gap = Number.parseFloat(style.columnGap) || 0\n boxWidthRef.current = hostRef.current?.parentElement?.clientWidth ?? -1\n\n // A hidden strip has no width to decide by: show every tab, and measure\n // when it appears (the observer sees the width change)\n if (available <= 0) {\n setVisibleCount(items.length)\n return\n }\n\n // The button with the active tab's name: that tab's width plus the chevron\n const chevron = moreButton?.querySelector(\"svg\")\n const chevronWidth = chevron?.getBoundingClientRect().width ?? 0\n const labelGap = chevron?.parentElement ? Number.parseFloat(getComputedStyle(chevron.parentElement).columnGap) || 0 : 0\n const activeWidth = activeIndex < 0 ? 0 : (widths[activeIndex] ?? 0) + chevronWidth + labelGap\n\n setVisibleCount(visibleTabCount(widths, moreWidth, activeWidth, activeIndex, gap, available))\n }, [visibleCount, items.length, activeIndex])\n\n // The width to fit is the container's, not the strip's: the strip shrinks\n // to its content. Reports during a measuring pass are skipped, since the\n // full strip may be pushing its container wider\n useEffect(() => {\n const box = hostRef.current?.parentElement\n if (!box || typeof ResizeObserver === \"undefined\") return\n const observer = new ResizeObserver(() => {\n if (measuringRef.current) return\n const width = box.clientWidth\n if (width === boxWidthRef.current) return\n boxWidthRef.current = width\n setVisibleCount(null)\n })\n observer.observe(box)\n return () => observer.disconnect()\n }, [])\n\n const measuring = visibleCount === null\n const shown = measuring ? items : items.slice(0, visibleCount)\n const hidden = measuring ? [] : items.slice(visibleCount)\n const hiddenActive = hidden.find((item) => item.props.value === value) ?? null\n\n return (\n <div ref={hostRef} className={s.OverflowHost}>\n <Menu>\n <TabsRoot<string>\n {...restProps}\n data-overflow=\"menu\"\n value={hiddenActive ? MORE_VALUE : value}\n onChange={(next) => {\n // Pressing the menu button opens the menu; it is not a tab\n if (next !== MORE_VALUE) onChange?.(next as T)\n }}\n >\n {/* Keyed by value: tabs from different fragments may share a key */}\n {shown.map((item) => cloneElement(item, { key: item.props.value }))}\n {(measuring || hidden.length > 0) && (\n <Menu.Trigger>\n <MoreTab value={MORE_VALUE}>\n <span className={s.OverflowLabel}>\n {hiddenActive ? tabLabel(hiddenActive) : overflowLabel}\n <ChevronDownMd />\n </span>\n </MoreTab>\n </Menu.Trigger>\n )}\n </TabsRoot>\n <Menu.Content align=\"end\" minWidth=\"auto\">\n <Menu.RadioGroup<string> value={value} onChange={(next) => onChange?.(next as T)}>\n {hidden.map((item) => {\n const count = badgeText(item.props.badge)\n return (\n <Menu.RadioItem<string>\n key={item.props.value}\n value={item.props.value}\n disabled={restProps.disabled || item.props.disabled}\n >\n {item.props.icon}\n {item.props.children ?? item.props[\"aria-label\"] ?? item.props.value}\n {/* A tab's count moves into the menu with it */}\n {count !== \"\" && <span className={s.OverflowBadge}>{count}</span>}\n </Menu.RadioItem>\n )\n })}\n </Menu.RadioGroup>\n </Menu.Content>\n </Menu>\n </div>\n )\n}\n\n// Attach sub-components\nTabs.Tab = Tab\n// Backward-compat alias\nTabs.Option = Tab\n"]}
|
|
@@ -12,7 +12,7 @@ const INPUT_CURSOR_TOLERANCE_PX = 10;
|
|
|
12
12
|
const CONTAINER_PADDING_PX = 24;
|
|
13
13
|
const SHAKE_ANIMATION_DURATION_MS = 500;
|
|
14
14
|
export const TagInput = (props) => {
|
|
15
|
-
const { defaultValue: defaultValueProp = [], value: controlledValue, size = "xl", onChange, validator, maxTags, placeholder = "", autoFocus = false, rows = 1, delimiters = [",", " "], disabled, pill = false, id, } = props;
|
|
15
|
+
const { defaultValue: defaultValueProp = [], value: controlledValue, size = "xl", variant = "outline", onChange, validator, maxTags, placeholder = "", autoFocus = false, rows = 1, delimiters = [",", " "], disabled, pill = false, id, } = props;
|
|
16
16
|
const [internalTags, setInternalTags] = useState(defaultValueProp);
|
|
17
17
|
const value = controlledValue ?? internalTags;
|
|
18
18
|
const isControlled = controlledValue !== undefined;
|
|
@@ -331,7 +331,7 @@ export const TagInput = (props) => {
|
|
|
331
331
|
};
|
|
332
332
|
// @ts-expect-error - Fix once usehooks-ts is updated https://github.com/juliencrn/usehooks-ts/pull/675
|
|
333
333
|
useOnClickOutside(containerRef, handleContainerBlur);
|
|
334
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { className: s.Container, ref: containerRef, onKeyDown: handleContainerKeyDown, onMouseDown: handleContainerMouseDown, onFocus: handleFocus, onBlur: handleBlur, "data-size": size, "data-focused": focused ? "" : undefined, "data-empty": tags.size === 0 ? "" : undefined, "data-pill": pill ? "" : undefined,
|
|
334
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { className: s.Container, ref: containerRef, onKeyDown: handleContainerKeyDown, onMouseDown: handleContainerMouseDown, onFocus: handleFocus, onBlur: handleBlur, "data-size": size, "data-variant": variant, "data-focused": focused ? "" : undefined, "data-empty": tags.size === 0 ? "" : undefined, "data-pill": pill ? "" : undefined,
|
|
335
335
|
// At maxTags the input is gone, so the container becomes the tab stop;
|
|
336
336
|
// arrow keys and Backspace then select and remove tags from here
|
|
337
337
|
tabIndex: showInput || disabled ? -1 : 0, style: toCssVariables({ "min-rows": String(rows) }), "data-disabled": disabled ? "" : undefined, children: _jsxs("div", { className: s.TagInput, children: [Array.from(tags.values()).map((tag) => (_jsxs("div", { className: s.Tag, tabIndex: -1, onClick: () => setSelectedTag(tag.value), "data-tag": tag.value, "data-invalid": !tag.valid ? "" : undefined, "data-duplicate": duplicateTags.has(tag.value) ? "" : undefined, children: [_jsx("span", { className: "overflow-hidden text-ellipsis", title: tag.value, children: _jsx("span", { className: s.TagValue, children: tag.value }) }), _jsx("div", { className: s.TagRemove, onClick: () => removeTag(tag.value), role: "button", "aria-label": "Remove item", children: _jsx(X, {}) })] }, tag.value))), showInput && (_jsxs("div", { className: s.InputContainer, children: [_jsx("span", { ref: measureRef, className: s.InputMeasure }), _jsx("div", { className: s.InputWrapper, children: _jsx("input", { id: id, className: s.Input, ref: inputRef, value: currentInput, onChange: (e) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TagInput.js","sourceRoot":"","sources":["../../../../src/components/TagInput/TagInput.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\"\nimport { useOnClickOutside } from \"usehooks-ts\"\nimport { useLatestValue } from \"../../hooks/useLatestValue\"\nimport { toCssVariables } from \"../../lib/helpers\"\nimport type { Sizes } from \"../../types\"\nimport { X } from \"../Icon\"\nimport s from \"@plexui/styles/components/TagInput/TagInput.module.css\"\n\nexport type Tag = {\n value: string\n valid: boolean\n}\n\nexport type TagInputProps = {\n /**\n * The state of the tag input when it is initially rendered, used when uncontrolled\n */\n defaultValue?: Tag[]\n /**\n * The value of the tag input, used to control the tag input\n */\n value?: Tag[]\n /**\n * Allows the tag input to be targeted with htmlFor\n */\n id?: string\n /**\n * Corresponds with Input height when rows=1\n * @default xl\n */\n size?: Sizes<\"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\" | \"3xl\">\n /**\n * Callback function invoked when the tag list changes\n */\n onChange?: (tags: Tag[]) => void\n /**\n * Placeholder text for the input\n */\n placeholder?: string\n /**\n * A function that returns whether a given value is a valid tag.\n * Invalid tags are highlighted in red.\n * Tags are evaluated for validity only on creation; changing the validator function later has no effect\n */\n validator?: (value: string) => boolean\n /**\n * The maximum number of tags allowed before the input is disabled; displays a counter below the input\n */\n maxTags?: number\n /**\n * Whether to focus this input on mount\n * @default false\n */\n autoFocus?: boolean\n /**\n * The minimum number of rows for the tag input\n * @default 1\n */\n rows?: number\n /**\n * Controls what characters will count towards creating a new tag\n * @default [\",\", \" \"]\n */\n delimiters?: string[]\n /**\n * Disables the tag input visually and from interactions\n */\n disabled?: boolean\n /**\n * Renders the container (and inner chips) with a fully-rounded radius,\n * matching `<Input pill />` and `<SelectControl pill />` for horizontal\n * filter rows that mix all three controls.\n * @default false\n */\n pill?: boolean\n}\n\n// How many pixels to reserve on the right of the input as a buffer before wrapping to the next line\nconst INPUT_CURSOR_TOLERANCE_PX = 10\n// The total space reserved on either side of the input for padding\nconst CONTAINER_PADDING_PX = 24\nconst SHAKE_ANIMATION_DURATION_MS = 500\n\nexport const TagInput = (props: TagInputProps) => {\n const {\n defaultValue: defaultValueProp = [],\n value: controlledValue,\n size = \"xl\",\n onChange,\n validator,\n maxTags,\n placeholder = \"\",\n autoFocus = false,\n rows = 1,\n delimiters = [\",\", \" \"],\n disabled,\n pill = false,\n id,\n } = props\n\n const [internalTags, setInternalTags] = useState(defaultValueProp)\n\n const value = controlledValue ?? internalTags\n const isControlled = controlledValue !== undefined\n\n const tags = useMemo(() => new Map(value.map((tag) => [tag.value, tag])), [value])\n\n const [currentInput, setCurrentInput] = useState(\"\")\n const [focused, setFocused] = useState(autoFocus)\n const [selectedTag, setSelectedTag] = useState<string | null>(null)\n const [duplicateTags, setDuplicateTags] = useState<Set<string>>(new Set())\n const [inputWidth, setInputWidth] = useState<number>(0)\n const validatorLatest = useLatestValue(validator)\n const onChangeLatest = useLatestValue(onChange)\n\n const inputRef = useRef<HTMLInputElement>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n const measureRef = useRef<HTMLSpanElement>(null)\n\n const showInput = !maxTags || tags.size < maxTags\n\n // Handle focusing the correct part of the tag input\n useEffect(() => {\n if (!focused || !containerRef.current) {\n return\n }\n const defaultFocusEl = inputRef.current ?? containerRef.current\n if (selectedTag === null) {\n defaultFocusEl.focus()\n } else {\n const selectedTagElement = containerRef.current.querySelector(\n `[data-tag=\"${CSS.escape(selectedTag)}\"]`,\n ) as HTMLElement | null\n if (selectedTagElement) {\n selectedTagElement.focus()\n } else {\n defaultFocusEl.focus()\n }\n }\n }, [focused, selectedTag, showInput]) // Include showInput so we focus the container when we hide the input\n\n const placeholderText = tags.size === 0 ? placeholder : undefined\n\n // Handle positioning the real input inside of the container.\n //\n // Reasons we need to recompute input width:\n // 1. Tags added / removed → last-tag right edge changes\n // 2. User typing into input → measured text width changes\n // 3. Container or chip dimensions change for any other reason —\n // window resize, font load, parent layout shift, OR a `size`/\n // `pill` prop flip that re-tunes chip height + font + gutter via\n // CSS variables. Without watching for (3), `inputWidth` stays\n // stale and the next typing flushes a one-off layout jump\n // (visible as an extra wrap row right after toggling size).\n //\n // ResizeObserver covers (3) — it fires whenever the container or any\n // chip changes box-size, including the synchronous CSS-var-driven\n // reflow on a `size` toggle.\n useLayoutEffect(() => {\n if (!containerRef.current || !measureRef.current) {\n return\n }\n const container = containerRef.current\n const measure = measureRef.current\n\n const recompute = () => {\n const containerRect = container.getBoundingClientRect()\n const tagElements = Array.from(\n container.querySelectorAll(\"[data-tag]\"),\n ) as HTMLDivElement[]\n\n // Grab the right edge of the last tag if it exists, otherwise the left edge of the container\n const leftBound =\n tagElements.length > 0\n ? tagElements[tagElements.length - 1].getBoundingClientRect().right\n : containerRect.left\n\n measure.textContent = currentInput || placeholderText || \"\"\n\n // By padding the text width, we ensure the input wraps to the next line\n // before we get to the point where we start to overflow\n const textWidth = measure.getBoundingClientRect().width + INPUT_CURSOR_TOLERANCE_PX\n\n // Calculate the remaining space based on the last tag's right edge (or container's left if no tags)\n const remainingSpace = containerRect.right - leftBound - CONTAINER_PADDING_PX\n\n if (textWidth <= remainingSpace) {\n setInputWidth(remainingSpace)\n } else {\n // We are going to flow to a new line, so recalculate remaining space based on the container size\n const width = containerRect.right - containerRect.left - CONTAINER_PADDING_PX\n setInputWidth(width)\n }\n }\n\n // Initial measurement (covers tags-array changes and typing).\n recompute()\n\n // Watch the container + every chip for any layout change. When `size`\n // changes the container itself usually keeps the same width (it's\n // `width: 100%`), but each chip's box does change — observing both\n // is the cheapest way to catch every relevant reflow.\n const observer = new ResizeObserver(recompute)\n observer.observe(container)\n const chips = container.querySelectorAll(\"[data-tag]\")\n chips.forEach((chip) => observer.observe(chip))\n\n return () => {\n observer.disconnect()\n }\n }, [currentInput, placeholderText, tags]) // Include tags so we reflow the container when we delete a tag\n\n // ============================================\n // Tag lifecycle functions\n // ============================================\n\n // Adds every value in one update: a paste of \"a,b\" must not compute\n // each addition from the same stale `tags` snapshot.\n const addTags = (tagValues: string[]) => {\n const newSet = new Map(tags)\n let changed = false\n for (const tagValue of tagValues) {\n if (maxTags && newSet.size >= maxTags) {\n break\n }\n const trimmed = tagValue.trim()\n if (!trimmed) {\n continue\n }\n if (newSet.has(trimmed)) {\n setDuplicateTags((prevTags) => new Set(prevTags).add(trimmed))\n setTimeout(\n () =>\n setDuplicateTags((prevTags) => {\n const newTags = new Set(prevTags)\n newTags.delete(trimmed)\n return newTags\n }),\n SHAKE_ANIMATION_DURATION_MS,\n )\n continue\n }\n const validTag = validatorLatest.current?.(trimmed) ?? true\n newSet.set(trimmed, { value: trimmed, valid: validTag })\n changed = true\n }\n if (!changed) {\n return\n }\n const newTags = Array.from(newSet.values())\n onChangeLatest.current?.(newTags)\n\n if (!isControlled) {\n setInternalTags(newTags)\n }\n }\n\n const addTag = (tagValue: string) => addTags([tagValue])\n\n const removeTag = (tag: string) => {\n if (disabled) {\n return\n }\n const newSet = new Map(tags)\n newSet.delete(tag)\n const newTags = Array.from(newSet.values())\n onChangeLatest.current?.(newTags)\n if (!isControlled) {\n setInternalTags(newTags)\n }\n if (selectedTag === tag) {\n setSelectedTag(null)\n }\n }\n\n const selectPreviousTag = () => {\n if (tags.size === 0) {\n return\n }\n const tagList = Array.from(tags.keys())\n if (selectedTag === null) {\n setSelectedTag(tagList[tagList.length - 1])\n } else {\n const prevIndex = tagList.indexOf(selectedTag)\n const index = Math.max(0, prevIndex - 1)\n setSelectedTag(tagList[index])\n }\n }\n\n const selectNextTag = () => {\n if (selectedTag === null) {\n return\n }\n const tagList = Array.from(tags.keys())\n const prevIndex = tagList.indexOf(selectedTag)\n const index = prevIndex + 1\n if (index < tagList.length) {\n setSelectedTag(tagList[index])\n } else {\n setSelectedTag(null)\n }\n }\n\n // ============================================\n // Helper functions\n // ============================================\n\n const isEmptyStartingSelection = () => {\n const input = inputRef.current\n if (!input) {\n return true\n }\n return input.selectionStart === 0 && input.selectionEnd === 0\n }\n\n const handleContainerBlur = () => {\n setFocused(false)\n setSelectedTag(null)\n // A disabled tag input keeps the pending text instead of committing it\n if (currentInput && !disabled) {\n addTag(currentInput)\n setCurrentInput(\"\")\n }\n }\n\n // ============================================\n // Event handlers\n // ============================================\n\n const handleContainerKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n // A tag can keep focus while the input turns disabled: no selecting or removing then\n if (disabled) {\n return\n }\n if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") {\n if (isEmptyStartingSelection()) {\n e.preventDefault()\n selectPreviousTag()\n }\n } else if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") {\n if (selectedTag !== null) {\n e.preventDefault()\n selectNextTag()\n }\n } else if (e.key === \"Backspace\") {\n if (selectedTag !== null) {\n removeTag(selectedTag)\n } else if (isEmptyStartingSelection()) {\n selectPreviousTag()\n }\n }\n }\n\n const handleInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" || delimiters.includes(e.key)) {\n e.preventDefault()\n if (currentInput) {\n addTag(currentInput)\n setCurrentInput(\"\")\n }\n } else if (e.key === \"Tab\") {\n if (currentInput) {\n e.preventDefault()\n addTag(currentInput)\n setCurrentInput(\"\")\n }\n }\n }\n\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n const text = e.clipboardData.getData(\"Text\")\n let parts = [text]\n\n // Split by all delimiters\n for (const delimiter of delimiters) {\n const newParts = []\n for (const segment of parts) {\n newParts.push(...segment.split(delimiter))\n }\n parts = newParts\n }\n\n // Remove empty parts\n parts = parts.filter(Boolean)\n\n if (parts.length > 1) {\n e.preventDefault()\n addTags(parts)\n }\n }\n\n const handleContainerMouseDown = (e: React.MouseEvent) => {\n // All clicks in the container focus the container\n setFocused(true)\n\n // If the click is on a tag pill, we are done. The click handler\n // for the specific tag will handle focusing it\n if (e.target && e.target instanceof Element && e.target.closest(\"[data-tag]\")) {\n return\n }\n\n // Since we know we didn't click a tag, clear any selected tag\n setSelectedTag(null)\n\n // If this click is outside of the input, prevent it from \"stealing\" focus from the input\n if (\n e.target &&\n e.target instanceof Element &&\n inputRef.current &&\n !inputRef.current.contains(e.target)\n ) {\n e.preventDefault()\n\n const { left, right, top, bottom } = inputRef.current.getBoundingClientRect()\n const { clientX, clientY } = e\n\n // If this is the first click, clear the selection. Otherwise, select the input contents\n if (e.detail === 1) {\n if (clientY < top || clientX < left) {\n // \"Before\" the input: top/left\n inputRef.current.setSelectionRange(0, 0)\n } else if (clientY > bottom || clientX > right) {\n // \"After\" the input: bottom/right\n const length = inputRef.current.value.length\n inputRef.current.setSelectionRange(length, length)\n }\n } else {\n inputRef.current.select()\n }\n }\n }\n\n const handleFocus = (e: React.FocusEvent) => {\n // If the focus is on a tag pill, do not trigger input focus logic\n // The click handler for the specific tag will handle it instead\n if (e.target && e.target instanceof Element && e.target.closest(\"[data-tag]\")) {\n return\n }\n setFocused(true)\n }\n\n const handleBlur = (e: React.FocusEvent) => {\n // If there is no related target, don't remove focus.\n // This occurs on a click inside the container but not on any element.\n // The handleClickOutside handler handles other cases\n if (!e.relatedTarget || !(e.relatedTarget instanceof Node)) {\n return\n }\n // Don't clear focus if focus is only moved elsewhere within the container\n if (containerRef.current && containerRef.current.contains(e.relatedTarget)) {\n // If we just tabbed into the input, clear the selected tag\n if (inputRef.current && inputRef.current.contains(e.relatedTarget)) {\n setSelectedTag(null)\n }\n return\n }\n handleContainerBlur()\n }\n\n // @ts-expect-error - Fix once usehooks-ts is updated https://github.com/juliencrn/usehooks-ts/pull/675\n useOnClickOutside(containerRef, handleContainerBlur)\n\n return (\n <>\n <div\n className={s.Container}\n ref={containerRef}\n onKeyDown={handleContainerKeyDown}\n onMouseDown={handleContainerMouseDown}\n onFocus={handleFocus}\n onBlur={handleBlur}\n data-size={size}\n data-focused={focused ? \"\" : undefined}\n data-empty={tags.size === 0 ? \"\" : undefined}\n data-pill={pill ? \"\" : undefined}\n // At maxTags the input is gone, so the container becomes the tab stop;\n // arrow keys and Backspace then select and remove tags from here\n tabIndex={showInput || disabled ? -1 : 0}\n style={toCssVariables({ \"min-rows\": String(rows) })}\n data-disabled={disabled ? \"\" : undefined}\n >\n <div className={s.TagInput}>\n {Array.from(tags.values()).map((tag) => (\n <div\n key={tag.value}\n className={s.Tag}\n tabIndex={-1}\n onClick={() => setSelectedTag(tag.value)}\n data-tag={tag.value}\n data-invalid={!tag.valid ? \"\" : undefined}\n data-duplicate={duplicateTags.has(tag.value) ? \"\" : undefined}\n >\n <span className=\"overflow-hidden text-ellipsis\" title={tag.value}>\n <span className={s.TagValue}>{tag.value}</span>\n </span>\n <div\n className={s.TagRemove}\n onClick={() => removeTag(tag.value)}\n role=\"button\"\n aria-label=\"Remove item\"\n >\n <X />\n </div>\n </div>\n ))}\n {showInput && (\n <div className={s.InputContainer}>\n {/* Hidden element to measure input width */}\n <span ref={measureRef} className={s.InputMeasure} />\n <div className={s.InputWrapper}>\n <input\n id={id}\n className={s.Input}\n ref={inputRef}\n value={currentInput}\n onChange={(e) => {\n setCurrentInput(e.target.value)\n }}\n onPaste={handlePaste}\n onKeyDown={handleInputKeyDown}\n placeholder={placeholderText}\n style={{ width: inputWidth }}\n disabled={disabled}\n />\n </div>\n </div>\n )}\n </div>\n </div>\n {/* 0 means no limit, as for the input above: no counter (and no stray \"0\") */}\n {maxTags ? (\n <div className={s.Limit}>\n {tags.size}\n <span className=\"mx-px\">/</span>\n {maxTags}\n </div>\n ) : null}\n </>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TagInput.js","sourceRoot":"","sources":["../../../../src/components/TagInput/TagInput.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\"\nimport { useOnClickOutside } from \"usehooks-ts\"\nimport { useLatestValue } from \"../../hooks/useLatestValue\"\nimport { toCssVariables } from \"../../lib/helpers\"\nimport type { Sizes, Variants } from \"../../types\"\nimport { X } from \"../Icon\"\nimport s from \"@plexui/styles/components/TagInput/TagInput.module.css\"\n\nexport type Tag = {\n value: string\n valid: boolean\n}\n\nexport type TagInputProps = {\n /**\n * The state of the tag input when it is initially rendered, used when uncontrolled\n */\n defaultValue?: Tag[]\n /**\n * The value of the tag input, used to control the tag input\n */\n value?: Tag[]\n /**\n * Allows the tag input to be targeted with htmlFor\n */\n id?: string\n /**\n * Corresponds with Input height when rows=1\n * @default xl\n */\n size?: Sizes<\"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\" | \"3xl\">\n /**\n * Visual style. `ghost` has no frame, for a field that its container already frames\n * @default outline\n */\n variant?: Variants<\"outline\" | \"ghost\">\n /**\n * Callback function invoked when the tag list changes\n */\n onChange?: (tags: Tag[]) => void\n /**\n * Placeholder text for the input\n */\n placeholder?: string\n /**\n * A function that returns whether a given value is a valid tag.\n * Invalid tags are highlighted in red.\n * Tags are evaluated for validity only on creation; changing the validator function later has no effect\n */\n validator?: (value: string) => boolean\n /**\n * The maximum number of tags allowed before the input is disabled; displays a counter below the input\n */\n maxTags?: number\n /**\n * Whether to focus this input on mount\n * @default false\n */\n autoFocus?: boolean\n /**\n * The minimum number of rows for the tag input\n * @default 1\n */\n rows?: number\n /**\n * Controls what characters will count towards creating a new tag\n * @default [\",\", \" \"]\n */\n delimiters?: string[]\n /**\n * Disables the tag input visually and from interactions\n */\n disabled?: boolean\n /**\n * Renders the container (and inner chips) with a fully-rounded radius,\n * matching `<Input pill />` and `<SelectControl pill />` for horizontal\n * filter rows that mix all three controls.\n * @default false\n */\n pill?: boolean\n}\n\n// How many pixels to reserve on the right of the input as a buffer before wrapping to the next line\nconst INPUT_CURSOR_TOLERANCE_PX = 10\n// The total space reserved on either side of the input for padding\nconst CONTAINER_PADDING_PX = 24\nconst SHAKE_ANIMATION_DURATION_MS = 500\n\nexport const TagInput = (props: TagInputProps) => {\n const {\n defaultValue: defaultValueProp = [],\n value: controlledValue,\n size = \"xl\",\n variant = \"outline\",\n onChange,\n validator,\n maxTags,\n placeholder = \"\",\n autoFocus = false,\n rows = 1,\n delimiters = [\",\", \" \"],\n disabled,\n pill = false,\n id,\n } = props\n\n const [internalTags, setInternalTags] = useState(defaultValueProp)\n\n const value = controlledValue ?? internalTags\n const isControlled = controlledValue !== undefined\n\n const tags = useMemo(() => new Map(value.map((tag) => [tag.value, tag])), [value])\n\n const [currentInput, setCurrentInput] = useState(\"\")\n const [focused, setFocused] = useState(autoFocus)\n const [selectedTag, setSelectedTag] = useState<string | null>(null)\n const [duplicateTags, setDuplicateTags] = useState<Set<string>>(new Set())\n const [inputWidth, setInputWidth] = useState<number>(0)\n const validatorLatest = useLatestValue(validator)\n const onChangeLatest = useLatestValue(onChange)\n\n const inputRef = useRef<HTMLInputElement>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n const measureRef = useRef<HTMLSpanElement>(null)\n\n const showInput = !maxTags || tags.size < maxTags\n\n // Handle focusing the correct part of the tag input\n useEffect(() => {\n if (!focused || !containerRef.current) {\n return\n }\n const defaultFocusEl = inputRef.current ?? containerRef.current\n if (selectedTag === null) {\n defaultFocusEl.focus()\n } else {\n const selectedTagElement = containerRef.current.querySelector(\n `[data-tag=\"${CSS.escape(selectedTag)}\"]`,\n ) as HTMLElement | null\n if (selectedTagElement) {\n selectedTagElement.focus()\n } else {\n defaultFocusEl.focus()\n }\n }\n }, [focused, selectedTag, showInput]) // Include showInput so we focus the container when we hide the input\n\n const placeholderText = tags.size === 0 ? placeholder : undefined\n\n // Handle positioning the real input inside of the container.\n //\n // Reasons we need to recompute input width:\n // 1. Tags added / removed → last-tag right edge changes\n // 2. User typing into input → measured text width changes\n // 3. Container or chip dimensions change for any other reason —\n // window resize, font load, parent layout shift, OR a `size`/\n // `pill` prop flip that re-tunes chip height + font + gutter via\n // CSS variables. Without watching for (3), `inputWidth` stays\n // stale and the next typing flushes a one-off layout jump\n // (visible as an extra wrap row right after toggling size).\n //\n // ResizeObserver covers (3) — it fires whenever the container or any\n // chip changes box-size, including the synchronous CSS-var-driven\n // reflow on a `size` toggle.\n useLayoutEffect(() => {\n if (!containerRef.current || !measureRef.current) {\n return\n }\n const container = containerRef.current\n const measure = measureRef.current\n\n const recompute = () => {\n const containerRect = container.getBoundingClientRect()\n const tagElements = Array.from(\n container.querySelectorAll(\"[data-tag]\"),\n ) as HTMLDivElement[]\n\n // Grab the right edge of the last tag if it exists, otherwise the left edge of the container\n const leftBound =\n tagElements.length > 0\n ? tagElements[tagElements.length - 1].getBoundingClientRect().right\n : containerRect.left\n\n measure.textContent = currentInput || placeholderText || \"\"\n\n // By padding the text width, we ensure the input wraps to the next line\n // before we get to the point where we start to overflow\n const textWidth = measure.getBoundingClientRect().width + INPUT_CURSOR_TOLERANCE_PX\n\n // Calculate the remaining space based on the last tag's right edge (or container's left if no tags)\n const remainingSpace = containerRect.right - leftBound - CONTAINER_PADDING_PX\n\n if (textWidth <= remainingSpace) {\n setInputWidth(remainingSpace)\n } else {\n // We are going to flow to a new line, so recalculate remaining space based on the container size\n const width = containerRect.right - containerRect.left - CONTAINER_PADDING_PX\n setInputWidth(width)\n }\n }\n\n // Initial measurement (covers tags-array changes and typing).\n recompute()\n\n // Watch the container + every chip for any layout change. When `size`\n // changes the container itself usually keeps the same width (it's\n // `width: 100%`), but each chip's box does change — observing both\n // is the cheapest way to catch every relevant reflow.\n const observer = new ResizeObserver(recompute)\n observer.observe(container)\n const chips = container.querySelectorAll(\"[data-tag]\")\n chips.forEach((chip) => observer.observe(chip))\n\n return () => {\n observer.disconnect()\n }\n }, [currentInput, placeholderText, tags]) // Include tags so we reflow the container when we delete a tag\n\n // ============================================\n // Tag lifecycle functions\n // ============================================\n\n // Adds every value in one update: a paste of \"a,b\" must not compute\n // each addition from the same stale `tags` snapshot.\n const addTags = (tagValues: string[]) => {\n const newSet = new Map(tags)\n let changed = false\n for (const tagValue of tagValues) {\n if (maxTags && newSet.size >= maxTags) {\n break\n }\n const trimmed = tagValue.trim()\n if (!trimmed) {\n continue\n }\n if (newSet.has(trimmed)) {\n setDuplicateTags((prevTags) => new Set(prevTags).add(trimmed))\n setTimeout(\n () =>\n setDuplicateTags((prevTags) => {\n const newTags = new Set(prevTags)\n newTags.delete(trimmed)\n return newTags\n }),\n SHAKE_ANIMATION_DURATION_MS,\n )\n continue\n }\n const validTag = validatorLatest.current?.(trimmed) ?? true\n newSet.set(trimmed, { value: trimmed, valid: validTag })\n changed = true\n }\n if (!changed) {\n return\n }\n const newTags = Array.from(newSet.values())\n onChangeLatest.current?.(newTags)\n\n if (!isControlled) {\n setInternalTags(newTags)\n }\n }\n\n const addTag = (tagValue: string) => addTags([tagValue])\n\n const removeTag = (tag: string) => {\n if (disabled) {\n return\n }\n const newSet = new Map(tags)\n newSet.delete(tag)\n const newTags = Array.from(newSet.values())\n onChangeLatest.current?.(newTags)\n if (!isControlled) {\n setInternalTags(newTags)\n }\n if (selectedTag === tag) {\n setSelectedTag(null)\n }\n }\n\n const selectPreviousTag = () => {\n if (tags.size === 0) {\n return\n }\n const tagList = Array.from(tags.keys())\n if (selectedTag === null) {\n setSelectedTag(tagList[tagList.length - 1])\n } else {\n const prevIndex = tagList.indexOf(selectedTag)\n const index = Math.max(0, prevIndex - 1)\n setSelectedTag(tagList[index])\n }\n }\n\n const selectNextTag = () => {\n if (selectedTag === null) {\n return\n }\n const tagList = Array.from(tags.keys())\n const prevIndex = tagList.indexOf(selectedTag)\n const index = prevIndex + 1\n if (index < tagList.length) {\n setSelectedTag(tagList[index])\n } else {\n setSelectedTag(null)\n }\n }\n\n // ============================================\n // Helper functions\n // ============================================\n\n const isEmptyStartingSelection = () => {\n const input = inputRef.current\n if (!input) {\n return true\n }\n return input.selectionStart === 0 && input.selectionEnd === 0\n }\n\n const handleContainerBlur = () => {\n setFocused(false)\n setSelectedTag(null)\n // A disabled tag input keeps the pending text instead of committing it\n if (currentInput && !disabled) {\n addTag(currentInput)\n setCurrentInput(\"\")\n }\n }\n\n // ============================================\n // Event handlers\n // ============================================\n\n const handleContainerKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n // A tag can keep focus while the input turns disabled: no selecting or removing then\n if (disabled) {\n return\n }\n if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") {\n if (isEmptyStartingSelection()) {\n e.preventDefault()\n selectPreviousTag()\n }\n } else if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") {\n if (selectedTag !== null) {\n e.preventDefault()\n selectNextTag()\n }\n } else if (e.key === \"Backspace\") {\n if (selectedTag !== null) {\n removeTag(selectedTag)\n } else if (isEmptyStartingSelection()) {\n selectPreviousTag()\n }\n }\n }\n\n const handleInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" || delimiters.includes(e.key)) {\n e.preventDefault()\n if (currentInput) {\n addTag(currentInput)\n setCurrentInput(\"\")\n }\n } else if (e.key === \"Tab\") {\n if (currentInput) {\n e.preventDefault()\n addTag(currentInput)\n setCurrentInput(\"\")\n }\n }\n }\n\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n const text = e.clipboardData.getData(\"Text\")\n let parts = [text]\n\n // Split by all delimiters\n for (const delimiter of delimiters) {\n const newParts = []\n for (const segment of parts) {\n newParts.push(...segment.split(delimiter))\n }\n parts = newParts\n }\n\n // Remove empty parts\n parts = parts.filter(Boolean)\n\n if (parts.length > 1) {\n e.preventDefault()\n addTags(parts)\n }\n }\n\n const handleContainerMouseDown = (e: React.MouseEvent) => {\n // All clicks in the container focus the container\n setFocused(true)\n\n // If the click is on a tag pill, we are done. The click handler\n // for the specific tag will handle focusing it\n if (e.target && e.target instanceof Element && e.target.closest(\"[data-tag]\")) {\n return\n }\n\n // Since we know we didn't click a tag, clear any selected tag\n setSelectedTag(null)\n\n // If this click is outside of the input, prevent it from \"stealing\" focus from the input\n if (\n e.target &&\n e.target instanceof Element &&\n inputRef.current &&\n !inputRef.current.contains(e.target)\n ) {\n e.preventDefault()\n\n const { left, right, top, bottom } = inputRef.current.getBoundingClientRect()\n const { clientX, clientY } = e\n\n // If this is the first click, clear the selection. Otherwise, select the input contents\n if (e.detail === 1) {\n if (clientY < top || clientX < left) {\n // \"Before\" the input: top/left\n inputRef.current.setSelectionRange(0, 0)\n } else if (clientY > bottom || clientX > right) {\n // \"After\" the input: bottom/right\n const length = inputRef.current.value.length\n inputRef.current.setSelectionRange(length, length)\n }\n } else {\n inputRef.current.select()\n }\n }\n }\n\n const handleFocus = (e: React.FocusEvent) => {\n // If the focus is on a tag pill, do not trigger input focus logic\n // The click handler for the specific tag will handle it instead\n if (e.target && e.target instanceof Element && e.target.closest(\"[data-tag]\")) {\n return\n }\n setFocused(true)\n }\n\n const handleBlur = (e: React.FocusEvent) => {\n // If there is no related target, don't remove focus.\n // This occurs on a click inside the container but not on any element.\n // The handleClickOutside handler handles other cases\n if (!e.relatedTarget || !(e.relatedTarget instanceof Node)) {\n return\n }\n // Don't clear focus if focus is only moved elsewhere within the container\n if (containerRef.current && containerRef.current.contains(e.relatedTarget)) {\n // If we just tabbed into the input, clear the selected tag\n if (inputRef.current && inputRef.current.contains(e.relatedTarget)) {\n setSelectedTag(null)\n }\n return\n }\n handleContainerBlur()\n }\n\n // @ts-expect-error - Fix once usehooks-ts is updated https://github.com/juliencrn/usehooks-ts/pull/675\n useOnClickOutside(containerRef, handleContainerBlur)\n\n return (\n <>\n <div\n className={s.Container}\n ref={containerRef}\n onKeyDown={handleContainerKeyDown}\n onMouseDown={handleContainerMouseDown}\n onFocus={handleFocus}\n onBlur={handleBlur}\n data-size={size}\n data-variant={variant}\n data-focused={focused ? \"\" : undefined}\n data-empty={tags.size === 0 ? \"\" : undefined}\n data-pill={pill ? \"\" : undefined}\n // At maxTags the input is gone, so the container becomes the tab stop;\n // arrow keys and Backspace then select and remove tags from here\n tabIndex={showInput || disabled ? -1 : 0}\n style={toCssVariables({ \"min-rows\": String(rows) })}\n data-disabled={disabled ? \"\" : undefined}\n >\n <div className={s.TagInput}>\n {Array.from(tags.values()).map((tag) => (\n <div\n key={tag.value}\n className={s.Tag}\n tabIndex={-1}\n onClick={() => setSelectedTag(tag.value)}\n data-tag={tag.value}\n data-invalid={!tag.valid ? \"\" : undefined}\n data-duplicate={duplicateTags.has(tag.value) ? \"\" : undefined}\n >\n <span className=\"overflow-hidden text-ellipsis\" title={tag.value}>\n <span className={s.TagValue}>{tag.value}</span>\n </span>\n <div\n className={s.TagRemove}\n onClick={() => removeTag(tag.value)}\n role=\"button\"\n aria-label=\"Remove item\"\n >\n <X />\n </div>\n </div>\n ))}\n {showInput && (\n <div className={s.InputContainer}>\n {/* Hidden element to measure input width */}\n <span ref={measureRef} className={s.InputMeasure} />\n <div className={s.InputWrapper}>\n <input\n id={id}\n className={s.Input}\n ref={inputRef}\n value={currentInput}\n onChange={(e) => {\n setCurrentInput(e.target.value)\n }}\n onPaste={handlePaste}\n onKeyDown={handleInputKeyDown}\n placeholder={placeholderText}\n style={{ width: inputWidth }}\n disabled={disabled}\n />\n </div>\n </div>\n )}\n </div>\n </div>\n {/* 0 means no limit, as for the input above: no counter (and no stray \"0\") */}\n {maxTags ? (\n <div className={s.Limit}>\n {tags.size}\n <span className=\"mx-px\">/</span>\n {maxTags}\n </div>\n ) : null}\n </>\n )\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Textarea.js","sourceRoot":"","sources":["../../../../src/components/Textarea/Textarea.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { useCallback, useEffect, useId, useRef, useState } from \"react\"\nimport { mergeRefs } from \"react-merge-refs\"\nimport { toCssVariables } from \"../../lib/helpers\"\nimport { type ControlSize, type Sizes, type Variants } from \"../../types\"\nimport s from \"@plexui/styles/components/Textarea/Textarea.module.css\"\n\nexport type TextareaProps = {\n /**\n * Visual style of the textarea\n * @default outline\n */\n variant?: Variants<\"outline\" | \"soft\">\n /**\n * Controls the size of the textarea\n *\n * | 3xs | 2xs | xs | sm | md | lg | xl | 2xl | 3xl |\n * | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- |\n * | `22px` | `24px` | `26px` | `28px` | `32px` | `36px` | `40px` | `44px` | `48px` |\n *\n * @default md\n */\n size?: ControlSize\n /**\n * Applies a negative margin using the current gutter to optically align the text with surrounding content.\n */\n opticallyAlign?: \"start\" | \"end\"\n /**\n * Controls gutter on the edges of the textarea, defaults to value from `size`.\n *\n * | 2xs | xs | sm | md | lg | xl |\n * | ------ | ------ | ------ | ------ | ------ | ------ |\n * | `6px` | `8px` | `10px` | `12px` | `14px` | `16px` |\n */\n gutterSize?: Sizes<\"2xs\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\">\n /**\n * Disables the textarea visually and from interactions\n * @default false\n */\n disabled?: boolean\n /**\n * Mark the textarea as invalid\n * @default false\n */\n invalid?: boolean\n /**\n * Allow autofill extensions to appear in the textarea\n * @default false\n */\n allowAutofillExtensions?: boolean\n /**\n * Select all contents of the textarea when mounted.\n * @default false\n */\n autoSelect?: boolean\n /** Callback invoked when the textarea is autofilled by the browser */\n onAutofill?: () => void\n /**\n * Default number of rows to display\n * @default 3\n */\n rows?: number\n /**\n * Automatically adjust the height of the textarea based on its contents.\n * @default false\n */\n autoResize?: boolean\n /**\n * Maximum number of rows that can be displayed when autoResize is enabled.\n * @default Math.max(rows, 10)\n */\n maxRows?: number\n /** Ref for the textarea */\n ref?: React.Ref<HTMLTextAreaElement | null>\n} & Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, \"disabled\" | \"size\">\n\nexport const Textarea = (props: TextareaProps) => {\n const textAreaRef = useRef<HTMLTextAreaElement | null>(null)\n const inputIdSuffix = useId()\n // Prevent 1Password from appearing: 1Password won't display if it thinks this field is for searching\n // Allow user to override this for connecting to labels.\n const onePasswordPreventionId = `search-ui-input-${inputIdSuffix}`\n const {\n id,\n name,\n variant = \"outline\",\n size = \"md\",\n opticallyAlign,\n gutterSize,\n className,\n autoComplete,\n disabled = false,\n readOnly = false,\n invalid = false,\n // Default to `true` when presence of `name`\n allowAutofillExtensions = !!name,\n onFocus,\n onBlur,\n onAnimationStart,\n onAutofill,\n autoSelect,\n rows = 3,\n maxRows,\n autoResize,\n ref,\n onChange,\n ...restProps\n } = props\n\n const [focused, setFocused] = useState<boolean>(false)\n const computedMaxRows = autoResize ? Math.max(maxRows ?? 10, rows) : rows\n\n useEffect(() => {\n if (autoSelect) {\n textAreaRef.current?.select()\n }\n }, [autoSelect])\n\n const handleAnimationStart = (evt: React.AnimationEvent<HTMLTextAreaElement>) => {\n onAnimationStart?.(evt)\n if (evt.animationName === \"native-autofill-in\") {\n onAutofill?.()\n }\n }\n\n const autosizeTextarea = useCallback(() => {\n if (!autoResize || !textAreaRef.current || computedMaxRows === undefined) return\n textAreaRef.current.style.height = \"0px\"\n const scrollHeight = textAreaRef.current.scrollHeight\n textAreaRef.current.style.height = scrollHeight + \"px\"\n }, [autoResize, computedMaxRows])\n\n // Resize if value changes outside of user input - e.g. form reset\n useEffect(() => {\n autosizeTextarea()\n }, [props.value, rows, autosizeTextarea])\n\n return (\n <div\n className={clsx(s.Container, className)}\n data-variant={variant}\n data-size={size}\n data-optically-align={opticallyAlign}\n data-gutter-size={gutterSize}\n data-focused={focused}\n data-disabled={disabled ? \"\" : undefined}\n data-readonly={readOnly ? \"\" : undefined}\n data-invalid={invalid ? \"\" : undefined}\n style={toCssVariables({\n \"textarea-min-rows\": `${rows}`,\n \"textarea-max-rows\": `${computedMaxRows}`,\n })}\n >\n <textarea\n {...restProps}\n onChange={(evt) => {\n onChange?.(evt)\n autosizeTextarea()\n }}\n ref={mergeRefs([textAreaRef, ref])}\n id={id || (allowAutofillExtensions ? undefined : onePasswordPreventionId)}\n className={s.Textarea}\n name={name}\n autoComplete={autoComplete}\n // Expose the visual invalid state to assistive tech; an explicit aria-invalid wins\n aria-invalid={restProps[\"aria-invalid\"] ?? (invalid || undefined)}\n readOnly={readOnly}\n disabled={disabled}\n rows={rows}\n onFocus={(evt) => {\n setFocused(true)\n onFocus?.(evt)\n }}\n onBlur={(evt) => {\n setFocused(false)\n onBlur?.(evt)\n }}\n onAnimationStart={handleAnimationStart}\n // Prevent LastPass and 1Password from appearing\n data-lpignore={allowAutofillExtensions ? undefined : true}\n data-1p-ignore={allowAutofillExtensions ? undefined : true}\n />\n </div>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Textarea.js","sourceRoot":"","sources":["../../../../src/components/Textarea/Textarea.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { useCallback, useEffect, useId, useRef, useState } from \"react\"\nimport { mergeRefs } from \"react-merge-refs\"\nimport { toCssVariables } from \"../../lib/helpers\"\nimport { type ControlSize, type Sizes, type Variants } from \"../../types\"\nimport s from \"@plexui/styles/components/Textarea/Textarea.module.css\"\n\nexport type TextareaProps = {\n /**\n * Visual style of the textarea\n * @default outline\n */\n variant?: Variants<\"outline\" | \"soft\" | \"ghost\">\n /**\n * Controls the size of the textarea\n *\n * | 3xs | 2xs | xs | sm | md | lg | xl | 2xl | 3xl |\n * | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- |\n * | `22px` | `24px` | `26px` | `28px` | `32px` | `36px` | `40px` | `44px` | `48px` |\n *\n * @default md\n */\n size?: ControlSize\n /**\n * Applies a negative margin using the current gutter to optically align the text with surrounding content.\n */\n opticallyAlign?: \"start\" | \"end\"\n /**\n * Controls gutter on the edges of the textarea, defaults to value from `size`.\n *\n * | 2xs | xs | sm | md | lg | xl |\n * | ------ | ------ | ------ | ------ | ------ | ------ |\n * | `6px` | `8px` | `10px` | `12px` | `14px` | `16px` |\n */\n gutterSize?: Sizes<\"2xs\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\">\n /**\n * Disables the textarea visually and from interactions\n * @default false\n */\n disabled?: boolean\n /**\n * Mark the textarea as invalid\n * @default false\n */\n invalid?: boolean\n /**\n * Allow autofill extensions to appear in the textarea\n * @default false\n */\n allowAutofillExtensions?: boolean\n /**\n * Select all contents of the textarea when mounted.\n * @default false\n */\n autoSelect?: boolean\n /** Callback invoked when the textarea is autofilled by the browser */\n onAutofill?: () => void\n /**\n * Default number of rows to display\n * @default 3\n */\n rows?: number\n /**\n * Automatically adjust the height of the textarea based on its contents.\n * @default false\n */\n autoResize?: boolean\n /**\n * Maximum number of rows that can be displayed when autoResize is enabled.\n * @default Math.max(rows, 10)\n */\n maxRows?: number\n /** Ref for the textarea */\n ref?: React.Ref<HTMLTextAreaElement | null>\n} & Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, \"disabled\" | \"size\">\n\nexport const Textarea = (props: TextareaProps) => {\n const textAreaRef = useRef<HTMLTextAreaElement | null>(null)\n const inputIdSuffix = useId()\n // Prevent 1Password from appearing: 1Password won't display if it thinks this field is for searching\n // Allow user to override this for connecting to labels.\n const onePasswordPreventionId = `search-ui-input-${inputIdSuffix}`\n const {\n id,\n name,\n variant = \"outline\",\n size = \"md\",\n opticallyAlign,\n gutterSize,\n className,\n autoComplete,\n disabled = false,\n readOnly = false,\n invalid = false,\n // Default to `true` when presence of `name`\n allowAutofillExtensions = !!name,\n onFocus,\n onBlur,\n onAnimationStart,\n onAutofill,\n autoSelect,\n rows = 3,\n maxRows,\n autoResize,\n ref,\n onChange,\n ...restProps\n } = props\n\n const [focused, setFocused] = useState<boolean>(false)\n const computedMaxRows = autoResize ? Math.max(maxRows ?? 10, rows) : rows\n\n useEffect(() => {\n if (autoSelect) {\n textAreaRef.current?.select()\n }\n }, [autoSelect])\n\n const handleAnimationStart = (evt: React.AnimationEvent<HTMLTextAreaElement>) => {\n onAnimationStart?.(evt)\n if (evt.animationName === \"native-autofill-in\") {\n onAutofill?.()\n }\n }\n\n const autosizeTextarea = useCallback(() => {\n if (!autoResize || !textAreaRef.current || computedMaxRows === undefined) return\n textAreaRef.current.style.height = \"0px\"\n const scrollHeight = textAreaRef.current.scrollHeight\n textAreaRef.current.style.height = scrollHeight + \"px\"\n }, [autoResize, computedMaxRows])\n\n // Resize if value changes outside of user input - e.g. form reset\n useEffect(() => {\n autosizeTextarea()\n }, [props.value, rows, autosizeTextarea])\n\n return (\n <div\n className={clsx(s.Container, className)}\n data-variant={variant}\n data-size={size}\n data-optically-align={opticallyAlign}\n data-gutter-size={gutterSize}\n data-focused={focused}\n data-disabled={disabled ? \"\" : undefined}\n data-readonly={readOnly ? \"\" : undefined}\n data-invalid={invalid ? \"\" : undefined}\n style={toCssVariables({\n \"textarea-min-rows\": `${rows}`,\n \"textarea-max-rows\": `${computedMaxRows}`,\n })}\n >\n <textarea\n {...restProps}\n onChange={(evt) => {\n onChange?.(evt)\n autosizeTextarea()\n }}\n ref={mergeRefs([textAreaRef, ref])}\n id={id || (allowAutofillExtensions ? undefined : onePasswordPreventionId)}\n className={s.Textarea}\n name={name}\n autoComplete={autoComplete}\n // Expose the visual invalid state to assistive tech; an explicit aria-invalid wins\n aria-invalid={restProps[\"aria-invalid\"] ?? (invalid || undefined)}\n readOnly={readOnly}\n disabled={disabled}\n rows={rows}\n onFocus={(evt) => {\n setFocused(true)\n onFocus?.(evt)\n }}\n onBlur={(evt) => {\n setFocused(false)\n onBlur?.(evt)\n }}\n onAnimationStart={handleAnimationStart}\n // Prevent LastPass and 1Password from appearing\n data-lpignore={allowAutofillExtensions ? undefined : true}\n data-1p-ignore={allowAutofillExtensions ? undefined : true}\n />\n </div>\n )\n}\n"]}
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import s from "@plexui/styles/components/Sortable/Sortable.module.css";
|
|
2
|
+
const START_DISTANCE = 4;
|
|
3
|
+
const TOUCH_HOLD = 200;
|
|
4
|
+
const SCROLL_EDGE = 80;
|
|
5
|
+
const SCROLL_SLOW = 4;
|
|
6
|
+
const SCROLL_FAST = 30;
|
|
7
|
+
const NEAR_LIST = 40;
|
|
8
|
+
const LINE_INSET = 16;
|
|
9
|
+
const PART = 4;
|
|
10
|
+
// --cubic-enter: an animation here cannot read a CSS variable
|
|
11
|
+
const EASING = "cubic-bezier(.19,1,.22,1)";
|
|
12
|
+
const HANDLE = "[data-sortable-handle]";
|
|
13
|
+
const INTERACTIVE = [
|
|
14
|
+
"a[href]",
|
|
15
|
+
"button",
|
|
16
|
+
"input",
|
|
17
|
+
"select",
|
|
18
|
+
"summary",
|
|
19
|
+
"textarea",
|
|
20
|
+
"[contenteditable]",
|
|
21
|
+
"[role=button]",
|
|
22
|
+
"[role=checkbox]",
|
|
23
|
+
"[role=combobox]",
|
|
24
|
+
"[role=link]",
|
|
25
|
+
"[role=radio]",
|
|
26
|
+
"[role=slider]",
|
|
27
|
+
"[role=switch]",
|
|
28
|
+
"[role=tab]",
|
|
29
|
+
].join(",");
|
|
30
|
+
// Read at the moment of use: the setting can change while the page is open
|
|
31
|
+
const reduced = () => window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
32
|
+
const itemsOf = (list) => [...list.children];
|
|
33
|
+
/** Grips stand in a table, elsewhere only when the list asks for them */
|
|
34
|
+
const showsHandles = (list) => (list.dataset.handles ?? String(list.tagName === "TBODY")) === "true";
|
|
35
|
+
/** The direct child of the list that holds `target` */
|
|
36
|
+
const itemOf = (list, target) => {
|
|
37
|
+
let node = target;
|
|
38
|
+
while (node && node.parentElement !== list)
|
|
39
|
+
node = node.parentElement;
|
|
40
|
+
return node;
|
|
41
|
+
};
|
|
42
|
+
/** The order after a move. `to` counts the list without the moved item. */
|
|
43
|
+
export const moveItem = (items, from, to) => {
|
|
44
|
+
const next = [...items];
|
|
45
|
+
next.splice(to, 0, ...next.splice(from, 1));
|
|
46
|
+
return next;
|
|
47
|
+
};
|
|
48
|
+
const labelOf = (item) => {
|
|
49
|
+
const named = item.dataset.sortableLabel ?? item.querySelector("[data-sortable-label], label")?.textContent;
|
|
50
|
+
if (named)
|
|
51
|
+
return named.trim();
|
|
52
|
+
// The cells of a row or the lines of a card run together: the first one is the name
|
|
53
|
+
const texts = document.createTreeWalker(item, NodeFilter.SHOW_TEXT);
|
|
54
|
+
while (texts.nextNode()) {
|
|
55
|
+
if (texts.currentNode.textContent?.trim())
|
|
56
|
+
return texts.currentNode.parentElement?.textContent?.trim() ?? "";
|
|
57
|
+
}
|
|
58
|
+
return "";
|
|
59
|
+
};
|
|
60
|
+
/** What a screen reader hears: a picture has no text of its own */
|
|
61
|
+
const nameOf = (item) => labelOf(item) || item.querySelector("img")?.alt || "";
|
|
62
|
+
function makeChip(item) {
|
|
63
|
+
const chip = document.createElement("div");
|
|
64
|
+
chip.className = s.Chip;
|
|
65
|
+
const image = item.querySelector("img");
|
|
66
|
+
if (image) {
|
|
67
|
+
const picture = document.createElement("img");
|
|
68
|
+
picture.className = s.ChipImage;
|
|
69
|
+
picture.src = image.currentSrc || image.src;
|
|
70
|
+
picture.alt = "";
|
|
71
|
+
chip.append(picture);
|
|
72
|
+
}
|
|
73
|
+
const text = labelOf(item);
|
|
74
|
+
if (text) {
|
|
75
|
+
const label = document.createElement("span");
|
|
76
|
+
label.className = s.ChipLabel;
|
|
77
|
+
label.textContent = text;
|
|
78
|
+
chip.append(label);
|
|
79
|
+
}
|
|
80
|
+
document.body.append(chip);
|
|
81
|
+
return chip;
|
|
82
|
+
}
|
|
83
|
+
function announce(text) {
|
|
84
|
+
let region = document.querySelector("[data-sortable-live]");
|
|
85
|
+
if (!region) {
|
|
86
|
+
region = document.createElement("div");
|
|
87
|
+
region.className = s.Live;
|
|
88
|
+
region.setAttribute("aria-live", "polite");
|
|
89
|
+
region.setAttribute("data-sortable-live", "");
|
|
90
|
+
document.body.append(region);
|
|
91
|
+
}
|
|
92
|
+
region.textContent = text;
|
|
93
|
+
}
|
|
94
|
+
const scrollParent = (list) => {
|
|
95
|
+
for (let node = list.parentElement; node && node !== document.body; node = node.parentElement) {
|
|
96
|
+
if (/auto|scroll/.test(getComputedStyle(node).overflowY) && node.scrollHeight > node.clientHeight)
|
|
97
|
+
return node;
|
|
98
|
+
}
|
|
99
|
+
return undefined;
|
|
100
|
+
};
|
|
101
|
+
// The nearer the edge the faster: slow to aim at a row, fast across a long list
|
|
102
|
+
const scrollStep = (depth) => SCROLL_SLOW + (SCROLL_FAST - SCROLL_SLOW) * Math.min(depth / SCROLL_EDGE, 1);
|
|
103
|
+
function listSlots(list, items) {
|
|
104
|
+
const box = list.getBoundingClientRect();
|
|
105
|
+
const rects = items.map((item) => item.getBoundingClientRect());
|
|
106
|
+
return Array.from({ length: items.length + 1 }, (_, gap) => {
|
|
107
|
+
const above = rects[gap - 1];
|
|
108
|
+
const below = rects[gap];
|
|
109
|
+
const y = above && below ? (above.bottom + below.top) / 2 : (below?.top ?? above.bottom);
|
|
110
|
+
return {
|
|
111
|
+
gap,
|
|
112
|
+
x: LINE_INSET,
|
|
113
|
+
y: y - box.top,
|
|
114
|
+
length: box.width - LINE_INSET * 2,
|
|
115
|
+
before: items[gap - 1],
|
|
116
|
+
after: items[gap],
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
// One slot per gap, and two where a line wraps: the end of one line and the start of the next
|
|
121
|
+
function gridSlots(list, items) {
|
|
122
|
+
const box = list.getBoundingClientRect();
|
|
123
|
+
const half = (parseFloat(getComputedStyle(list).columnGap) || 8) / 2;
|
|
124
|
+
const rects = items.map((item) => item.getBoundingClientRect());
|
|
125
|
+
const slots = [];
|
|
126
|
+
const add = (gap, x, rect, before, after) => slots.push({ gap, x: x - box.left, y: rect.top - box.top, length: rect.height, before, after });
|
|
127
|
+
rects.forEach((rect, gap) => {
|
|
128
|
+
const previous = rects[gap - 1];
|
|
129
|
+
if (previous && Math.abs(previous.top - rect.top) < rect.height / 2) {
|
|
130
|
+
add(gap, (previous.right + rect.left) / 2, rect, items[gap - 1], items[gap]);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (previous)
|
|
134
|
+
add(gap, previous.right + half, previous, items[gap - 1]);
|
|
135
|
+
add(gap, rect.left - half, rect, undefined, items[gap]);
|
|
136
|
+
});
|
|
137
|
+
const last = rects.length - 1;
|
|
138
|
+
add(rects.length, rects[last].right + half, rects[last], items[last]);
|
|
139
|
+
return slots;
|
|
140
|
+
}
|
|
141
|
+
// The chip keeps its size and fades out: grown to the item, its text would stand over the item's own
|
|
142
|
+
function flyChip(chip, to, layout) {
|
|
143
|
+
if (reduced() || !to) {
|
|
144
|
+
chip.remove();
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const from = chip.getBoundingClientRect();
|
|
148
|
+
const x = layout === "grid" ? to.left + (to.width - from.width) / 2 : to.left;
|
|
149
|
+
const y = to.top + (to.height - from.height) / 2;
|
|
150
|
+
chip.animate([
|
|
151
|
+
{ transform: `translate(${from.left}px, ${from.top}px)`, opacity: 1 },
|
|
152
|
+
{ transform: `translate(${x}px, ${y}px)`, opacity: 0 },
|
|
153
|
+
], { duration: 200, easing: EASING, fill: "forwards" }).onfinish = () => chip.remove();
|
|
154
|
+
}
|
|
155
|
+
/** The items that changed place slide there from where they stood */
|
|
156
|
+
async function commitWithFlip(items, from, to, commit, skip) {
|
|
157
|
+
const before = new Map(items.map((item) => [item, item.getBoundingClientRect()]));
|
|
158
|
+
await commit(from, to);
|
|
159
|
+
if (reduced())
|
|
160
|
+
return;
|
|
161
|
+
items
|
|
162
|
+
.filter((item) => item !== skip && item.isConnected)
|
|
163
|
+
.forEach((item) => {
|
|
164
|
+
const was = before.get(item);
|
|
165
|
+
const now = item.getBoundingClientRect();
|
|
166
|
+
const x = was.left - now.left;
|
|
167
|
+
const y = was.top - now.top;
|
|
168
|
+
if (x || y)
|
|
169
|
+
item.animate([{ transform: `translate(${x}px, ${y}px)` }, { transform: "none" }], { duration: 200, easing: EASING });
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
const swallow = (event) => {
|
|
173
|
+
event.stopPropagation();
|
|
174
|
+
event.preventDefault();
|
|
175
|
+
};
|
|
176
|
+
function startDrag(event, list, source, layout, immediate, commit) {
|
|
177
|
+
const touch = event.pointerType === "touch" && !immediate;
|
|
178
|
+
const origin = { x: event.clientX, y: event.clientY };
|
|
179
|
+
const pointer = { ...origin };
|
|
180
|
+
const holdTimer = touch ? setTimeout(begin, TOUCH_HOLD) : undefined;
|
|
181
|
+
const style = getComputedStyle(list);
|
|
182
|
+
const part = parseFloat(layout === "grid" ? style.columnGap : style.rowGap) ? PART : 0;
|
|
183
|
+
const scroller = scrollParent(list);
|
|
184
|
+
let drag;
|
|
185
|
+
window.addEventListener("pointermove", onMove);
|
|
186
|
+
window.addEventListener("pointerup", onUp);
|
|
187
|
+
window.addEventListener("pointercancel", onCancel);
|
|
188
|
+
function onMove({ clientX, clientY }) {
|
|
189
|
+
pointer.x = clientX;
|
|
190
|
+
pointer.y = clientY;
|
|
191
|
+
if (drag)
|
|
192
|
+
return;
|
|
193
|
+
const moved = Math.hypot(clientX - origin.x, clientY - origin.y) >= START_DISTANCE;
|
|
194
|
+
if (moved && touch)
|
|
195
|
+
stopListening();
|
|
196
|
+
else if (moved)
|
|
197
|
+
begin();
|
|
198
|
+
}
|
|
199
|
+
function onUp() {
|
|
200
|
+
finish(true);
|
|
201
|
+
}
|
|
202
|
+
function onCancel() {
|
|
203
|
+
finish(false);
|
|
204
|
+
}
|
|
205
|
+
function onKey(keyEvent) {
|
|
206
|
+
if (keyEvent.key !== "Escape")
|
|
207
|
+
return;
|
|
208
|
+
keyEvent.stopPropagation();
|
|
209
|
+
finish(false);
|
|
210
|
+
}
|
|
211
|
+
function blockScroll(touchEvent) {
|
|
212
|
+
touchEvent.preventDefault();
|
|
213
|
+
}
|
|
214
|
+
function stopListening() {
|
|
215
|
+
clearTimeout(holdTimer);
|
|
216
|
+
window.removeEventListener("pointermove", onMove);
|
|
217
|
+
window.removeEventListener("pointerup", onUp);
|
|
218
|
+
window.removeEventListener("pointercancel", onCancel);
|
|
219
|
+
window.removeEventListener("keydown", onKey, true);
|
|
220
|
+
window.removeEventListener("touchmove", blockScroll);
|
|
221
|
+
}
|
|
222
|
+
function begin() {
|
|
223
|
+
const items = itemsOf(list);
|
|
224
|
+
const slots = layout === "grid" ? gridSlots(list, items) : listSlots(list, items);
|
|
225
|
+
window.getSelection()?.removeAllRanges();
|
|
226
|
+
document.documentElement.classList.add(s.Dragging);
|
|
227
|
+
list.setAttribute("data-dragging", "");
|
|
228
|
+
source.setAttribute("data-sortable-source", "");
|
|
229
|
+
window.addEventListener("keydown", onKey, true);
|
|
230
|
+
window.addEventListener("touchmove", blockScroll, { passive: false });
|
|
231
|
+
const chip = makeChip(source);
|
|
232
|
+
const line = document.createElement("div");
|
|
233
|
+
line.className = s.Line;
|
|
234
|
+
line.hidden = true;
|
|
235
|
+
document.body.append(line);
|
|
236
|
+
const { width, height } = chip.getBoundingClientRect();
|
|
237
|
+
drag = { chip, line, width, height, items, slots };
|
|
238
|
+
tick();
|
|
239
|
+
}
|
|
240
|
+
function tick() {
|
|
241
|
+
if (!drag)
|
|
242
|
+
return;
|
|
243
|
+
autoScroll();
|
|
244
|
+
update();
|
|
245
|
+
drag.frame = requestAnimationFrame(tick);
|
|
246
|
+
}
|
|
247
|
+
function autoScroll() {
|
|
248
|
+
const box = scroller?.getBoundingClientRect() ?? { top: 0, bottom: window.innerHeight };
|
|
249
|
+
const above = box.top + SCROLL_EDGE - pointer.y;
|
|
250
|
+
const below = pointer.y - box.bottom + SCROLL_EDGE;
|
|
251
|
+
const step = above > 0 ? -scrollStep(above) : below > 0 ? scrollStep(below) : 0;
|
|
252
|
+
if (!step)
|
|
253
|
+
return;
|
|
254
|
+
if (scroller)
|
|
255
|
+
scroller.scrollTop += step;
|
|
256
|
+
else
|
|
257
|
+
window.scrollBy(0, step);
|
|
258
|
+
}
|
|
259
|
+
function update() {
|
|
260
|
+
if (!drag)
|
|
261
|
+
return;
|
|
262
|
+
drag.chip.style.transform = `translate(${pointer.x - drag.width / 2}px, ${pointer.y - drag.height / 2}px)`;
|
|
263
|
+
const box = source.getBoundingClientRect();
|
|
264
|
+
const overSource = pointer.x >= box.left && pointer.x <= box.right && pointer.y >= box.top && pointer.y <= box.bottom;
|
|
265
|
+
source.toggleAttribute("data-sortable-away", !overSource);
|
|
266
|
+
showGap(overSource ? undefined : nearestSlot());
|
|
267
|
+
}
|
|
268
|
+
function nearestSlot() {
|
|
269
|
+
if (!drag)
|
|
270
|
+
return undefined;
|
|
271
|
+
const box = list.getBoundingClientRect();
|
|
272
|
+
const near = pointer.x >= box.left - NEAR_LIST &&
|
|
273
|
+
pointer.x <= box.right + NEAR_LIST &&
|
|
274
|
+
pointer.y >= box.top - NEAR_LIST &&
|
|
275
|
+
pointer.y <= box.bottom + NEAR_LIST;
|
|
276
|
+
if (!near)
|
|
277
|
+
return undefined;
|
|
278
|
+
const distance = (slot) => {
|
|
279
|
+
if (layout === "list")
|
|
280
|
+
return Math.abs(pointer.y - (box.top + slot.y));
|
|
281
|
+
const top = box.top + slot.y;
|
|
282
|
+
return Math.hypot(pointer.x - (box.left + slot.x), Math.max(top - pointer.y, 0, pointer.y - top - slot.length));
|
|
283
|
+
};
|
|
284
|
+
const best = drag.slots.reduce((nearest, slot) => (distance(slot) < distance(nearest) ? slot : nearest));
|
|
285
|
+
const index = drag.items.indexOf(source);
|
|
286
|
+
return best.gap === index || best.gap === index + 1 ? undefined : best;
|
|
287
|
+
}
|
|
288
|
+
function shift(slot, distance) {
|
|
289
|
+
const move = (item, by) => {
|
|
290
|
+
if (!item || !part)
|
|
291
|
+
return;
|
|
292
|
+
item.style.transform = distance
|
|
293
|
+
? layout === "grid"
|
|
294
|
+
? `translateX(${by}px)`
|
|
295
|
+
: `translateY(${by}px)`
|
|
296
|
+
: "";
|
|
297
|
+
};
|
|
298
|
+
move(slot?.before, -distance);
|
|
299
|
+
move(slot?.after, distance);
|
|
300
|
+
}
|
|
301
|
+
function showGap(found) {
|
|
302
|
+
if (!drag)
|
|
303
|
+
return;
|
|
304
|
+
if (found !== drag.found) {
|
|
305
|
+
shift(drag.found, 0);
|
|
306
|
+
shift(found, part);
|
|
307
|
+
}
|
|
308
|
+
drag.found = found;
|
|
309
|
+
drag.line.hidden = !found;
|
|
310
|
+
if (!found)
|
|
311
|
+
return;
|
|
312
|
+
const box = list.getBoundingClientRect();
|
|
313
|
+
if (layout === "grid") {
|
|
314
|
+
drag.line.style.transform = `translate(${box.left + found.x - 1}px, ${box.top + found.y}px)`;
|
|
315
|
+
drag.line.style.height = `${found.length}px`;
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
drag.line.style.transform = `translate(${box.left + found.x}px, ${box.top + found.y - 1}px)`;
|
|
319
|
+
drag.line.style.width = `${found.length}px`;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
function restoreSource() {
|
|
323
|
+
source.removeAttribute("data-sortable-source");
|
|
324
|
+
source.removeAttribute("data-sortable-away");
|
|
325
|
+
}
|
|
326
|
+
function settle(chip) {
|
|
327
|
+
flyChip(chip, source.isConnected ? source.getBoundingClientRect() : undefined, layout);
|
|
328
|
+
if (!reduced() && source.isConnected)
|
|
329
|
+
source.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 250, easing: EASING });
|
|
330
|
+
}
|
|
331
|
+
async function land(chip, items, { gap }, clear) {
|
|
332
|
+
const from = items.indexOf(source);
|
|
333
|
+
const to = gap > from ? gap - 1 : gap;
|
|
334
|
+
restoreSource();
|
|
335
|
+
const clearAndCommit = (moved, place) => {
|
|
336
|
+
clear();
|
|
337
|
+
return commit(moved, place);
|
|
338
|
+
};
|
|
339
|
+
await commitWithFlip(items, from, to, clearAndCommit, source);
|
|
340
|
+
announce(`${nameOf(source)}, ${to + 1} / ${items.length}`);
|
|
341
|
+
settle(chip);
|
|
342
|
+
}
|
|
343
|
+
function finish(drop) {
|
|
344
|
+
stopListening();
|
|
345
|
+
if (!drag)
|
|
346
|
+
return;
|
|
347
|
+
const { chip, line, found, items, frame } = drag;
|
|
348
|
+
if (frame)
|
|
349
|
+
cancelAnimationFrame(frame);
|
|
350
|
+
// The pointer lifts over a row: that click must not act on it
|
|
351
|
+
window.addEventListener("click", swallow, { capture: true, once: true });
|
|
352
|
+
setTimeout(() => window.removeEventListener("click", swallow, { capture: true }));
|
|
353
|
+
line.remove();
|
|
354
|
+
drag = undefined;
|
|
355
|
+
// On a drop this waits for the flip to read where the parted items stand
|
|
356
|
+
const clear = () => {
|
|
357
|
+
list.removeAttribute("data-dragging");
|
|
358
|
+
document.documentElement.classList.remove(s.Dragging);
|
|
359
|
+
shift(found, 0);
|
|
360
|
+
};
|
|
361
|
+
if (drop && found) {
|
|
362
|
+
void land(chip, items, found, clear);
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
clear();
|
|
366
|
+
restoreSource();
|
|
367
|
+
settle(chip);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
/** Starts a drag from a press inside the list. Goes on the list's `pointerdown`. */
|
|
371
|
+
export function sortablePointerDown(event, list, layout, commit) {
|
|
372
|
+
const target = event.target;
|
|
373
|
+
if (event.button || target.closest("[data-sortable]") !== list)
|
|
374
|
+
return;
|
|
375
|
+
const source = itemOf(list, target);
|
|
376
|
+
if (!source)
|
|
377
|
+
return;
|
|
378
|
+
const handle = target.closest(HANDLE);
|
|
379
|
+
// A grip in sight is the only way to drag, otherwise anything but a control starts it
|
|
380
|
+
if (source.querySelector(HANDLE) && showsHandles(list) ? !handle : target.closest(INTERACTIVE))
|
|
381
|
+
return;
|
|
382
|
+
startDrag(event, list, source, layout, !!handle, commit);
|
|
383
|
+
}
|
|
384
|
+
const KEY_STEPS = { ArrowUp: -1, ArrowLeft: -1, ArrowDown: 1, ArrowRight: 1 };
|
|
385
|
+
/** Moves the focused handle's item with the arrow keys. Goes on the list's `keydown`. */
|
|
386
|
+
export async function sortableKeyDown(event, list, commit) {
|
|
387
|
+
const step = KEY_STEPS[event.key];
|
|
388
|
+
const target = event.target;
|
|
389
|
+
if (!step || target.closest("[data-sortable]") !== list)
|
|
390
|
+
return;
|
|
391
|
+
const source = itemOf(list, target);
|
|
392
|
+
if (!source || (target !== source && !target.closest(HANDLE)))
|
|
393
|
+
return;
|
|
394
|
+
const items = itemsOf(list);
|
|
395
|
+
const from = items.indexOf(source);
|
|
396
|
+
const to = from + step;
|
|
397
|
+
if (to < 0 || to >= items.length)
|
|
398
|
+
return;
|
|
399
|
+
event.preventDefault();
|
|
400
|
+
await commitWithFlip(items, from, to, commit);
|
|
401
|
+
// Moving an element in the document drops its focus
|
|
402
|
+
if (target.isConnected && document.activeElement !== target)
|
|
403
|
+
target.focus();
|
|
404
|
+
announce(`${nameOf(source)}, ${to + 1} / ${items.length}`);
|
|
405
|
+
}
|
|
406
|
+
//# sourceMappingURL=sortable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sortable.js","sourceRoot":"","sources":["../../../src/lib/sortable.ts"],"names":[],"mappings":"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","sourcesContent":["import s from \"@plexui/styles/components/Sortable/Sortable.module.css\"\n\n// Drag to reorder, for any list of elements. Nothing moves until the drop: the\n// item leaves a flat slot and shrinks to a chip at the cursor, a line marks the\n// nearest gap, and only the drop changes the order. Items that stand apart part\n// at the gap. Rows that touch hold still: their text would run over the hairlines.\n\nexport type SortableLayout = \"list\" | \"grid\"\n\n/** Applies a move to the list. Resolves once the DOM shows the new order. */\nexport type SortableCommit = (from: number, to: number) => void | Promise<void>\n\ntype Slot = {\n gap: number\n /** Offsets from the list's corner, so a scroll under the drag keeps them true */\n x: number\n y: number\n length: number\n before?: Element\n after?: Element\n}\n\nconst START_DISTANCE = 4\nconst TOUCH_HOLD = 200\nconst SCROLL_EDGE = 80\nconst SCROLL_SLOW = 4\nconst SCROLL_FAST = 30\nconst NEAR_LIST = 40\nconst LINE_INSET = 16\nconst PART = 4\n// --cubic-enter: an animation here cannot read a CSS variable\nconst EASING = \"cubic-bezier(.19,1,.22,1)\"\nconst HANDLE = \"[data-sortable-handle]\"\nconst INTERACTIVE = [\n \"a[href]\",\n \"button\",\n \"input\",\n \"select\",\n \"summary\",\n \"textarea\",\n \"[contenteditable]\",\n \"[role=button]\",\n \"[role=checkbox]\",\n \"[role=combobox]\",\n \"[role=link]\",\n \"[role=radio]\",\n \"[role=slider]\",\n \"[role=switch]\",\n \"[role=tab]\",\n].join(\",\")\n\n// Read at the moment of use: the setting can change while the page is open\nconst reduced = () => window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches\n\nconst itemsOf = (list: HTMLElement) => [...list.children] as HTMLElement[]\n\n/** Grips stand in a table, elsewhere only when the list asks for them */\nconst showsHandles = (list: HTMLElement) => (list.dataset.handles ?? String(list.tagName === \"TBODY\")) === \"true\"\n\n/** The direct child of the list that holds `target` */\nconst itemOf = (list: HTMLElement, target: Element) => {\n let node: Element | null = target\n while (node && node.parentElement !== list) node = node.parentElement\n return node as HTMLElement | null\n}\n\n/** The order after a move. `to` counts the list without the moved item. */\nexport const moveItem = <T>(items: readonly T[], from: number, to: number) => {\n const next = [...items]\n next.splice(to, 0, ...next.splice(from, 1))\n return next\n}\n\nconst labelOf = (item: HTMLElement) => {\n const named = item.dataset.sortableLabel ?? item.querySelector(\"[data-sortable-label], label\")?.textContent\n if (named) return named.trim()\n // The cells of a row or the lines of a card run together: the first one is the name\n const texts = document.createTreeWalker(item, NodeFilter.SHOW_TEXT)\n while (texts.nextNode()) {\n if (texts.currentNode.textContent?.trim()) return texts.currentNode.parentElement?.textContent?.trim() ?? \"\"\n }\n return \"\"\n}\n\n/** What a screen reader hears: a picture has no text of its own */\nconst nameOf = (item: HTMLElement) => labelOf(item) || item.querySelector(\"img\")?.alt || \"\"\n\nfunction makeChip(item: HTMLElement) {\n const chip = document.createElement(\"div\")\n chip.className = s.Chip\n const image = item.querySelector(\"img\")\n if (image) {\n const picture = document.createElement(\"img\")\n picture.className = s.ChipImage\n picture.src = image.currentSrc || image.src\n picture.alt = \"\"\n chip.append(picture)\n }\n const text = labelOf(item)\n if (text) {\n const label = document.createElement(\"span\")\n label.className = s.ChipLabel\n label.textContent = text\n chip.append(label)\n }\n document.body.append(chip)\n return chip\n}\n\nfunction announce(text: string) {\n let region = document.querySelector(\"[data-sortable-live]\")\n if (!region) {\n region = document.createElement(\"div\")\n region.className = s.Live\n region.setAttribute(\"aria-live\", \"polite\")\n region.setAttribute(\"data-sortable-live\", \"\")\n document.body.append(region)\n }\n region.textContent = text\n}\n\nconst scrollParent = (list: HTMLElement) => {\n for (let node = list.parentElement; node && node !== document.body; node = node.parentElement) {\n if (/auto|scroll/.test(getComputedStyle(node).overflowY) && node.scrollHeight > node.clientHeight) return node\n }\n return undefined\n}\n\n// The nearer the edge the faster: slow to aim at a row, fast across a long list\nconst scrollStep = (depth: number) =>\n SCROLL_SLOW + (SCROLL_FAST - SCROLL_SLOW) * Math.min(depth / SCROLL_EDGE, 1)\n\nfunction listSlots(list: HTMLElement, items: HTMLElement[]) {\n const box = list.getBoundingClientRect()\n const rects = items.map((item) => item.getBoundingClientRect())\n return Array.from({ length: items.length + 1 }, (_, gap): Slot => {\n const above = rects[gap - 1]\n const below = rects[gap]\n const y = above && below ? (above.bottom + below.top) / 2 : (below?.top ?? above.bottom)\n return {\n gap,\n x: LINE_INSET,\n y: y - box.top,\n length: box.width - LINE_INSET * 2,\n before: items[gap - 1],\n after: items[gap],\n }\n })\n}\n\n// One slot per gap, and two where a line wraps: the end of one line and the start of the next\nfunction gridSlots(list: HTMLElement, items: HTMLElement[]) {\n const box = list.getBoundingClientRect()\n const half = (parseFloat(getComputedStyle(list).columnGap) || 8) / 2\n const rects = items.map((item) => item.getBoundingClientRect())\n const slots: Slot[] = []\n const add = (gap: number, x: number, rect: DOMRect, before?: Element, after?: Element) =>\n slots.push({ gap, x: x - box.left, y: rect.top - box.top, length: rect.height, before, after })\n\n rects.forEach((rect, gap) => {\n const previous = rects[gap - 1]\n if (previous && Math.abs(previous.top - rect.top) < rect.height / 2) {\n add(gap, (previous.right + rect.left) / 2, rect, items[gap - 1], items[gap])\n return\n }\n if (previous) add(gap, previous.right + half, previous, items[gap - 1])\n add(gap, rect.left - half, rect, undefined, items[gap])\n })\n const last = rects.length - 1\n add(rects.length, rects[last].right + half, rects[last], items[last])\n return slots\n}\n\n// The chip keeps its size and fades out: grown to the item, its text would stand over the item's own\nfunction flyChip(chip: HTMLElement, to: DOMRect | undefined, layout: SortableLayout) {\n if (reduced() || !to) {\n chip.remove()\n return\n }\n const from = chip.getBoundingClientRect()\n const x = layout === \"grid\" ? to.left + (to.width - from.width) / 2 : to.left\n const y = to.top + (to.height - from.height) / 2\n chip.animate(\n [\n { transform: `translate(${from.left}px, ${from.top}px)`, opacity: 1 },\n { transform: `translate(${x}px, ${y}px)`, opacity: 0 },\n ],\n { duration: 200, easing: EASING, fill: \"forwards\" },\n ).onfinish = () => chip.remove()\n}\n\n/** The items that changed place slide there from where they stood */\nasync function commitWithFlip(items: HTMLElement[], from: number, to: number, commit: SortableCommit, skip?: HTMLElement) {\n const before = new Map(items.map((item) => [item, item.getBoundingClientRect()]))\n await commit(from, to)\n if (reduced()) return\n items\n .filter((item) => item !== skip && item.isConnected)\n .forEach((item) => {\n const was = before.get(item) as DOMRect\n const now = item.getBoundingClientRect()\n const x = was.left - now.left\n const y = was.top - now.top\n if (x || y) item.animate([{ transform: `translate(${x}px, ${y}px)` }, { transform: \"none\" }], { duration: 200, easing: EASING })\n })\n}\n\nconst swallow = (event: Event) => {\n event.stopPropagation()\n event.preventDefault()\n}\n\nfunction startDrag(event: PointerEvent, list: HTMLElement, source: HTMLElement, layout: SortableLayout, immediate: boolean, commit: SortableCommit) {\n const touch = event.pointerType === \"touch\" && !immediate\n const origin = { x: event.clientX, y: event.clientY }\n const pointer = { ...origin }\n const holdTimer = touch ? setTimeout(begin, TOUCH_HOLD) : undefined\n const style = getComputedStyle(list)\n const part = parseFloat(layout === \"grid\" ? style.columnGap : style.rowGap) ? PART : 0\n const scroller = scrollParent(list)\n let drag:\n | {\n chip: HTMLElement\n line: HTMLElement\n width: number\n height: number\n items: HTMLElement[]\n slots: Slot[]\n frame?: number\n found?: Slot\n }\n | undefined\n\n window.addEventListener(\"pointermove\", onMove)\n window.addEventListener(\"pointerup\", onUp)\n window.addEventListener(\"pointercancel\", onCancel)\n\n function onMove({ clientX, clientY }: PointerEvent) {\n pointer.x = clientX\n pointer.y = clientY\n if (drag) return\n const moved = Math.hypot(clientX - origin.x, clientY - origin.y) >= START_DISTANCE\n if (moved && touch) stopListening()\n else if (moved) begin()\n }\n\n function onUp() {\n finish(true)\n }\n\n function onCancel() {\n finish(false)\n }\n\n function onKey(keyEvent: KeyboardEvent) {\n if (keyEvent.key !== \"Escape\") return\n keyEvent.stopPropagation()\n finish(false)\n }\n\n function blockScroll(touchEvent: TouchEvent) {\n touchEvent.preventDefault()\n }\n\n function stopListening() {\n clearTimeout(holdTimer)\n window.removeEventListener(\"pointermove\", onMove)\n window.removeEventListener(\"pointerup\", onUp)\n window.removeEventListener(\"pointercancel\", onCancel)\n window.removeEventListener(\"keydown\", onKey, true)\n window.removeEventListener(\"touchmove\", blockScroll)\n }\n\n function begin() {\n const items = itemsOf(list)\n const slots = layout === \"grid\" ? gridSlots(list, items) : listSlots(list, items)\n window.getSelection()?.removeAllRanges()\n document.documentElement.classList.add(s.Dragging)\n list.setAttribute(\"data-dragging\", \"\")\n source.setAttribute(\"data-sortable-source\", \"\")\n window.addEventListener(\"keydown\", onKey, true)\n window.addEventListener(\"touchmove\", blockScroll, { passive: false })\n const chip = makeChip(source)\n const line = document.createElement(\"div\")\n line.className = s.Line\n line.hidden = true\n document.body.append(line)\n const { width, height } = chip.getBoundingClientRect()\n drag = { chip, line, width, height, items, slots }\n tick()\n }\n\n function tick() {\n if (!drag) return\n autoScroll()\n update()\n drag.frame = requestAnimationFrame(tick)\n }\n\n function autoScroll() {\n const box = scroller?.getBoundingClientRect() ?? { top: 0, bottom: window.innerHeight }\n const above = box.top + SCROLL_EDGE - pointer.y\n const below = pointer.y - box.bottom + SCROLL_EDGE\n const step = above > 0 ? -scrollStep(above) : below > 0 ? scrollStep(below) : 0\n if (!step) return\n if (scroller) scroller.scrollTop += step\n else window.scrollBy(0, step)\n }\n\n function update() {\n if (!drag) return\n drag.chip.style.transform = `translate(${pointer.x - drag.width / 2}px, ${pointer.y - drag.height / 2}px)`\n const box = source.getBoundingClientRect()\n const overSource = pointer.x >= box.left && pointer.x <= box.right && pointer.y >= box.top && pointer.y <= box.bottom\n source.toggleAttribute(\"data-sortable-away\", !overSource)\n showGap(overSource ? undefined : nearestSlot())\n }\n\n function nearestSlot() {\n if (!drag) return undefined\n const box = list.getBoundingClientRect()\n const near =\n pointer.x >= box.left - NEAR_LIST &&\n pointer.x <= box.right + NEAR_LIST &&\n pointer.y >= box.top - NEAR_LIST &&\n pointer.y <= box.bottom + NEAR_LIST\n if (!near) return undefined\n const distance = (slot: Slot) => {\n if (layout === \"list\") return Math.abs(pointer.y - (box.top + slot.y))\n const top = box.top + slot.y\n return Math.hypot(pointer.x - (box.left + slot.x), Math.max(top - pointer.y, 0, pointer.y - top - slot.length))\n }\n const best = drag.slots.reduce((nearest, slot) => (distance(slot) < distance(nearest) ? slot : nearest))\n const index = drag.items.indexOf(source)\n return best.gap === index || best.gap === index + 1 ? undefined : best\n }\n\n function shift(slot: Slot | undefined, distance: number) {\n const move = (item: Element | undefined, by: number) => {\n if (!item || !part) return\n ;(item as HTMLElement).style.transform = distance\n ? layout === \"grid\"\n ? `translateX(${by}px)`\n : `translateY(${by}px)`\n : \"\"\n }\n move(slot?.before, -distance)\n move(slot?.after, distance)\n }\n\n function showGap(found: Slot | undefined) {\n if (!drag) return\n if (found !== drag.found) {\n shift(drag.found, 0)\n shift(found, part)\n }\n drag.found = found\n drag.line.hidden = !found\n if (!found) return\n const box = list.getBoundingClientRect()\n if (layout === \"grid\") {\n drag.line.style.transform = `translate(${box.left + found.x - 1}px, ${box.top + found.y}px)`\n drag.line.style.height = `${found.length}px`\n } else {\n drag.line.style.transform = `translate(${box.left + found.x}px, ${box.top + found.y - 1}px)`\n drag.line.style.width = `${found.length}px`\n }\n }\n\n function restoreSource() {\n source.removeAttribute(\"data-sortable-source\")\n source.removeAttribute(\"data-sortable-away\")\n }\n\n function settle(chip: HTMLElement) {\n flyChip(chip, source.isConnected ? source.getBoundingClientRect() : undefined, layout)\n if (!reduced() && source.isConnected) source.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 250, easing: EASING })\n }\n\n async function land(chip: HTMLElement, items: HTMLElement[], { gap }: Slot, clear: () => void) {\n const from = items.indexOf(source)\n const to = gap > from ? gap - 1 : gap\n restoreSource()\n const clearAndCommit: SortableCommit = (moved, place) => {\n clear()\n return commit(moved, place)\n }\n await commitWithFlip(items, from, to, clearAndCommit, source)\n announce(`${nameOf(source)}, ${to + 1} / ${items.length}`)\n settle(chip)\n }\n\n function finish(drop: boolean) {\n stopListening()\n if (!drag) return\n const { chip, line, found, items, frame } = drag\n if (frame) cancelAnimationFrame(frame)\n // The pointer lifts over a row: that click must not act on it\n window.addEventListener(\"click\", swallow, { capture: true, once: true })\n setTimeout(() => window.removeEventListener(\"click\", swallow, { capture: true }))\n line.remove()\n drag = undefined\n // On a drop this waits for the flip to read where the parted items stand\n const clear = () => {\n list.removeAttribute(\"data-dragging\")\n document.documentElement.classList.remove(s.Dragging)\n shift(found, 0)\n }\n if (drop && found) {\n void land(chip, items, found, clear)\n return\n }\n clear()\n restoreSource()\n settle(chip)\n }\n}\n\n/** Starts a drag from a press inside the list. Goes on the list's `pointerdown`. */\nexport function sortablePointerDown(event: PointerEvent, list: HTMLElement, layout: SortableLayout, commit: SortableCommit) {\n const target = event.target as Element\n if (event.button || target.closest(\"[data-sortable]\") !== list) return\n const source = itemOf(list, target)\n if (!source) return\n const handle = target.closest(HANDLE)\n // A grip in sight is the only way to drag, otherwise anything but a control starts it\n if (source.querySelector(HANDLE) && showsHandles(list) ? !handle : target.closest(INTERACTIVE)) return\n startDrag(event, list, source, layout, !!handle, commit)\n}\n\nconst KEY_STEPS: Record<string, number> = { ArrowUp: -1, ArrowLeft: -1, ArrowDown: 1, ArrowRight: 1 }\n\n/** Moves the focused handle's item with the arrow keys. Goes on the list's `keydown`. */\nexport async function sortableKeyDown(event: KeyboardEvent, list: HTMLElement, commit: SortableCommit) {\n const step = KEY_STEPS[event.key]\n const target = event.target as HTMLElement\n if (!step || target.closest(\"[data-sortable]\") !== list) return\n const source = itemOf(list, target)\n if (!source || (target !== source && !target.closest(HANDLE))) return\n const items = itemsOf(list)\n const from = items.indexOf(source)\n const to = from + step\n if (to < 0 || to >= items.length) return\n event.preventDefault()\n await commitWithFlip(items, from, to, commit)\n // Moving an element in the document drops its focus\n if (target.isConnected && document.activeElement !== target) target.focus()\n announce(`${nameOf(source)}, ${to + 1} / ${items.length}`)\n}\n"]}
|
|
@@ -20,7 +20,7 @@ export type RadioGroupProps<T extends string> = {
|
|
|
20
20
|
};
|
|
21
21
|
export declare const RadioGroup: {
|
|
22
22
|
<T extends string>({ onChange, children, className, direction, disabled, ...restProps }: RadioGroupProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
23
|
-
Item: <T extends string>({ value, disabled: itemDisabled, required, children, description, className, block, orientation, ...restProps }: RadioGroupItemProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
Item: <T extends string>({ value, disabled: itemDisabled, required, children, description, className, block, orientation, id: idProp, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, ...restProps }: RadioGroupItemProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
24
24
|
};
|
|
25
25
|
export type RadioGroupItemProps<T extends string> = {
|
|
26
26
|
value: T;
|
|
@@ -35,7 +35,13 @@ export type RadioGroupItemProps<T extends string> = {
|
|
|
35
35
|
* @default "left"
|
|
36
36
|
*/
|
|
37
37
|
orientation?: "left" | "right";
|
|
38
|
-
|
|
38
|
+
/** Id of the radio, so a label outside the item can target it with `htmlFor` */
|
|
39
|
+
id?: string;
|
|
40
|
+
"aria-label"?: string;
|
|
41
|
+
"aria-labelledby"?: string;
|
|
42
|
+
"aria-describedby"?: string;
|
|
43
|
+
/** The option's label. Leave it out when a `Field` around the item names it. */
|
|
44
|
+
children?: React.ReactNode;
|
|
39
45
|
/** Optional second line below the option's label. Linked via `aria-describedby`. */
|
|
40
46
|
description?: React.ReactNode;
|
|
41
47
|
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ComponentProps, ElementType, ReactNode } from "react";
|
|
2
|
+
import { type SortableLayout } from "../../lib/sortable.js";
|
|
3
|
+
export type SortableProps<T> = {
|
|
4
|
+
/**
|
|
5
|
+
* The list, in the order of the children
|
|
6
|
+
*/
|
|
7
|
+
value: readonly T[];
|
|
8
|
+
/**
|
|
9
|
+
* Called with the new order after a drop
|
|
10
|
+
*/
|
|
11
|
+
onChange?: (value: T[]) => void;
|
|
12
|
+
/**
|
|
13
|
+
* `list` for rows one under another, `grid` for items that stand side by side
|
|
14
|
+
* @default list
|
|
15
|
+
*/
|
|
16
|
+
layout?: SortableLayout;
|
|
17
|
+
/**
|
|
18
|
+
* Element to render, such as `TableBody` for table rows
|
|
19
|
+
* @default div
|
|
20
|
+
*/
|
|
21
|
+
as?: ElementType;
|
|
22
|
+
/**
|
|
23
|
+
* Turns dragging off
|
|
24
|
+
* @default false
|
|
25
|
+
*/
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Shows the grips of `Sortable.Handle`. A hidden grip still takes the keyboard, and the item drags from anywhere but a control.
|
|
29
|
+
* @default true in a table, otherwise false
|
|
30
|
+
*/
|
|
31
|
+
handles?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* The items, one direct child per entry of `value`, keyed by the entry and not by its index
|
|
34
|
+
*/
|
|
35
|
+
children?: ReactNode;
|
|
36
|
+
} & Omit<ComponentProps<"div">, "children" | "onChange">;
|
|
37
|
+
/** Reorders its direct children by dragging, from anywhere but a control, or by a `Sortable.Handle` where grips are shown. */
|
|
38
|
+
export declare function Sortable<T>({ value, onChange, layout, as: Tag, disabled, handles, className, children, onPointerDown, onKeyDown, ...rest }: SortableProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
export declare namespace Sortable {
|
|
40
|
+
var Handle: typeof SortableHandle;
|
|
41
|
+
}
|
|
42
|
+
export type SortableHandleProps = {
|
|
43
|
+
/**
|
|
44
|
+
* Name of the handle for assistive technology
|
|
45
|
+
* @default Reorder
|
|
46
|
+
*/
|
|
47
|
+
"aria-label"?: string;
|
|
48
|
+
} & ComponentProps<"button">;
|
|
49
|
+
/** The grip of an item. Arrow keys move the item while the handle has focus. */
|
|
50
|
+
declare function SortableHandle({ "aria-label": ariaLabel, className, children, ...rest }: SortableHandleProps): import("react/jsx-runtime").JSX.Element;
|
|
51
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Sortable, type SortableHandleProps, type SortableProps } from "./Sortable.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Sizes } from "../../types.js";
|
|
1
|
+
import type { Sizes, Variants } from "../../types.js";
|
|
2
2
|
export type Tag = {
|
|
3
3
|
value: string;
|
|
4
4
|
valid: boolean;
|
|
@@ -21,6 +21,11 @@ export type TagInputProps = {
|
|
|
21
21
|
* @default xl
|
|
22
22
|
*/
|
|
23
23
|
size?: Sizes<"sm" | "md" | "lg" | "xl" | "2xl" | "3xl">;
|
|
24
|
+
/**
|
|
25
|
+
* Visual style. `ghost` has no frame, for a field that its container already frames
|
|
26
|
+
* @default outline
|
|
27
|
+
*/
|
|
28
|
+
variant?: Variants<"outline" | "ghost">;
|
|
24
29
|
/**
|
|
25
30
|
* Callback function invoked when the tag list changes
|
|
26
31
|
*/
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type SortableLayout = "list" | "grid";
|
|
2
|
+
/** Applies a move to the list. Resolves once the DOM shows the new order. */
|
|
3
|
+
export type SortableCommit = (from: number, to: number) => void | Promise<void>;
|
|
4
|
+
/** The order after a move. `to` counts the list without the moved item. */
|
|
5
|
+
export declare const moveItem: <T>(items: readonly T[], from: number, to: number) => T[];
|
|
6
|
+
/** Starts a drag from a press inside the list. Goes on the list's `pointerdown`. */
|
|
7
|
+
export declare function sortablePointerDown(event: PointerEvent, list: HTMLElement, layout: SortableLayout, commit: SortableCommit): void;
|
|
8
|
+
/** Moves the focused handle's item with the arrow keys. Goes on the list's `keydown`. */
|
|
9
|
+
export declare function sortableKeyDown(event: KeyboardEvent, list: HTMLElement, commit: SortableCommit): Promise<void>;
|