@namroodinc/liquid-editorial 0.1.10 → 0.2.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/AGENTS.md +1 -1
- package/README.md +32 -16
- package/UPGRADING.md +68 -0
- package/dist/chunks/FormEditor-8bz3pOdP.cjs +2 -0
- package/dist/chunks/FormEditor-8bz3pOdP.cjs.map +1 -0
- package/dist/chunks/FormEditor-DuW8x78Y.js +330 -0
- package/dist/chunks/FormEditor-DuW8x78Y.js.map +1 -0
- package/dist/components/AppShell/index.cjs +1 -1
- package/dist/components/AppShell/index.cjs.map +1 -1
- package/dist/components/AppShell/index.d.cts.map +1 -1
- package/dist/components/AppShell/index.d.ts.map +1 -1
- package/dist/components/AppShell/index.js +1 -0
- package/dist/components/AppShell/index.js.map +1 -1
- package/dist/components/Badge/style.css +24 -21
- package/dist/components/Drawer/index.cjs +1 -1
- package/dist/components/Drawer/index.cjs.map +1 -1
- package/dist/components/Drawer/index.d.cts +3 -2
- package/dist/components/Drawer/index.d.cts.map +1 -1
- package/dist/components/Drawer/index.d.ts +3 -2
- package/dist/components/Drawer/index.d.ts.map +1 -1
- package/dist/components/Drawer/index.js +11 -10
- package/dist/components/Drawer/index.js.map +1 -1
- package/dist/components/Drawer/style.css +37 -79
- package/dist/components/EntryPicker/index.cjs +1 -1
- package/dist/components/EntryPicker/index.cjs.map +1 -1
- package/dist/components/EntryPicker/index.d.cts +3 -1
- package/dist/components/EntryPicker/index.d.cts.map +1 -1
- package/dist/components/EntryPicker/index.d.ts +3 -1
- package/dist/components/EntryPicker/index.d.ts.map +1 -1
- package/dist/components/EntryPicker/index.js +45 -43
- package/dist/components/EntryPicker/index.js.map +1 -1
- package/dist/components/FormEditor/control.d.cts +15 -0
- package/dist/components/FormEditor/control.d.cts.map +1 -0
- package/dist/components/FormEditor/control.d.ts +15 -0
- package/dist/components/FormEditor/control.d.ts.map +1 -0
- package/dist/components/FormEditor/index.cjs +1 -0
- package/dist/components/FormEditor/index.d.cts +28 -0
- package/dist/components/FormEditor/index.d.cts.map +1 -0
- package/dist/components/FormEditor/index.d.ts +28 -0
- package/dist/components/FormEditor/index.d.ts.map +1 -0
- package/dist/components/FormEditor/index.js +2 -0
- package/dist/components/FormEditor/model.d.cts +86 -0
- package/dist/components/FormEditor/model.d.cts.map +1 -0
- package/dist/components/FormEditor/model.d.ts +86 -0
- package/dist/components/FormEditor/model.d.ts.map +1 -0
- package/dist/components/FormEditor/style.css +25 -0
- package/dist/components/NumberField/index.cjs +1 -1
- package/dist/components/NumberField/index.cjs.map +1 -1
- package/dist/components/NumberField/index.d.cts +3 -0
- package/dist/components/NumberField/index.d.cts.map +1 -1
- package/dist/components/NumberField/index.d.ts +3 -0
- package/dist/components/NumberField/index.d.ts.map +1 -1
- package/dist/components/NumberField/index.js +20 -20
- package/dist/components/NumberField/index.js.map +1 -1
- package/dist/components/RichTextEditor/index.cjs +1 -1
- package/dist/components/RichTextEditor/index.js +0 -1
- package/dist/components/SelectionCard/index.cjs +1 -1
- package/dist/components/SelectionCard/index.cjs.map +1 -1
- package/dist/components/SelectionCard/index.d.cts +4 -1
- package/dist/components/SelectionCard/index.d.cts.map +1 -1
- package/dist/components/SelectionCard/index.d.ts +4 -1
- package/dist/components/SelectionCard/index.d.ts.map +1 -1
- package/dist/components/SelectionCard/index.js +3 -3
- package/dist/components/SelectionCard/index.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -20
- package/dist/styles.css +1 -1
- package/dist/tokens.css +15 -5
- package/package.json +1 -1
- package/dist/chunks/EntryEditor-CcyYtH74.js +0 -191
- package/dist/chunks/EntryEditor-CcyYtH74.js.map +0 -1
- package/dist/chunks/EntryEditor-DIpc1iPF.cjs +0 -2
- package/dist/chunks/EntryEditor-DIpc1iPF.cjs.map +0 -1
- package/dist/components/EntryEditor/index.cjs +0 -1
- package/dist/components/EntryEditor/index.d.cts +0 -21
- package/dist/components/EntryEditor/index.d.cts.map +0 -1
- package/dist/components/EntryEditor/index.d.ts +0 -21
- package/dist/components/EntryEditor/index.d.ts.map +0 -1
- package/dist/components/EntryEditor/index.js +0 -6
- package/dist/components/EntryEditor/model.d.cts +0 -33
- package/dist/components/EntryEditor/model.d.cts.map +0 -1
- package/dist/components/EntryEditor/model.d.ts +0 -33
- package/dist/components/EntryEditor/model.d.ts.map +0 -1
- package/dist/components/EntryEditor/style.css +0 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormEditor-DuW8x78Y.js","names":["documentError","emptyDocument","RichTextEditor","fieldTypes","assertModel","ids","field","model","linkCopy","pickerCopy","defaults","rest","parseUtcDateTime","value","match","canonical","date","isLink","key","hasRichText","node","requiredError","textError","richTextError","error","choiceError","option","linkError","itemLabel","item","itemsLabel","max","validators","fieldError","validateFormValues","values","selectedIds","link","id","pickerValue","links","NumberControl","NumberField","accessibility","stored","next","onChange","SelectControl","isClearable","required","Select","PickerControl","EntryPicker","FormControl","shared","TextField","isDisabled","event","TextArea","Switch","FormEditorField","validation","useMemo","isErrorVisible","label","Field","FormEditor","internal","setInternal","useState","defaultValue","changed","setChanged","current","schema","commit","fieldId","previous","onValueChange","layout","columns","minColumnWidth","className","style","fieldDisabled","isLocked","showAllErrors","pickerItems","errors"],"sources":["../../src/components/FormEditor/model.ts","../../src/components/FormEditor/control.tsx","../../src/components/FormEditor/index.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { SelectOption } from \"../Select\";\nimport type { EntryPickerProps } from \"../EntryPicker\";\nimport type { JSONContent } from \"@tiptap/react\";\nimport { documentError } from \"../RichTextEditor/document\";\nimport type { RichTextDocument } from \"../RichTextEditor\";\n\ninterface FormFieldBase {\n id: string;\n label: string;\n hint?: ReactNode;\n placeholder?: string;\n required?: boolean;\n isDisabled?: boolean;\n}\n\nexport type FormField = FormFieldBase & (\n | { type: \"shortText\"; inputType?: \"text\" | \"email\"; maxLength?: number; readOnly?: boolean; autoFocus?: boolean; multiple?: never }\n | { type: \"longText\"; rows?: number; maxLength?: number; readOnly?: boolean; autoFocus?: boolean; multiple?: never }\n | { type: \"boolean\" | \"dateTime\"; autoFocus?: boolean; multiple?: never }\n | { type: \"richText\"; autoFocus?: never; multiple?: never }\n | { type: \"number\"; min?: number; max?: number; step?: number | \"any\"; hasSteppers?: boolean; autoFocus?: boolean; multiple?: never }\n | { type: \"select\"; options: SelectOption[]; autoFocus?: boolean; multiple?: never }\n | { type: \"asset\" | \"reference\"; multiple?: boolean; autoFocus?: never; picker?: Pick<EntryPickerProps, \"label\" | \"addLabel\" | \"emptyLabel\" | \"itemLabel\" | \"itemsLabel\" | \"max\" | \"isReorderable\"> }\n);\n\nexport type FieldOf<T extends FormField[\"type\"]> = Extract<FormField, { type: T }>;\n\nexport interface FormSchema {\n fields: readonly FormField[];\n}\n\nexport interface AssetValue { assetId: string }\nexport interface ReferenceValue { entryId: string }\nexport type FormFieldValue = string | number | boolean | RichTextDocument | AssetValue | ReferenceValue | AssetValue[] | ReferenceValue[];\nexport type FormValues = Record<string, FormFieldValue | undefined>;\nexport type FormErrors = Partial<Record<string, string>>;\n\nconst fieldTypes = new Set([\"shortText\", \"longText\", \"richText\", \"number\", \"boolean\", \"dateTime\", \"asset\", \"reference\", \"select\"]);\n\nexport function assertModel(model: FormSchema) {\n const ids = new Set<string>();\n for (const field of model.fields) {\n if (!field.id?.trim() || ids.has(field.id)) throw new Error(\"Form field IDs must be nonempty and unique.\");\n if (!fieldTypes.has(field.type)) throw new Error(`Unsupported form field type: ${field.type}`);\n if (field.type === \"select\" && !Array.isArray(field.options)) throw new Error(`Select field ${field.id} needs an options array.`);\n ids.add(field.id);\n }\n}\n\nconst linkCopy = {\n asset: { key: \"assetId\", label: \"Assets\", itemLabel: \"asset\", itemsLabel: \"assets\" },\n reference: { key: \"entryId\", label: \"Entries\", itemLabel: \"entry\", itemsLabel: \"entries\" },\n} as const;\n\n/** Picker copy, with asset or entry wording for any option the field leaves out or sets to undefined. */\nexport function pickerCopy(field: FieldOf<\"asset\" | \"reference\">) {\n const defaults = linkCopy[field.type];\n const {\n label = defaults.label,\n addLabel = `Choose ${field.label}`,\n itemLabel = defaults.itemLabel,\n itemsLabel = defaults.itemsLabel,\n ...rest\n } = field.picker ?? {};\n return { ...rest, label, addLabel, itemLabel, itemsLabel };\n}\n\n/** Accept UTC ISO strings without rolling invalid dates into the next month. */\nexport function parseUtcDateTime(value: unknown): string | undefined {\n if (typeof value !== \"string\") return;\n const match = /^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2})(?::(\\d{2})(?:\\.(\\d{1,3}))?)?(?:Z|\\+00:00)$/.exec(value);\n if (!match) return;\n const canonical = `${match[1]}:${match[2] ?? \"00\"}.${(match[3] ?? \"\").padEnd(3, \"0\")}Z`;\n const date = new Date(canonical);\n if (Number.isFinite(date.getTime()) && date.toISOString() === canonical) return canonical;\n}\n\nfunction isLink(value: unknown, key: \"assetId\" | \"entryId\"): boolean {\n return !!value && typeof value === \"object\" && key in value &&\n typeof (value as Record<string, unknown>)[key] === \"string\" &&\n ((value as Record<string, string>)[key]).trim().length > 0;\n}\n\nfunction hasRichText(node: JSONContent): boolean {\n return !!node.text?.trim() || node.type === \"horizontalRule\" || !!node.content?.some(hasRichText);\n}\n\nfunction requiredError(field: FormField): string {\n return `${field.label} is required.`;\n}\n\nfunction textError(field: FormField, value: unknown): string | undefined {\n if (typeof value !== \"string\") return \"Enter text.\";\n if (field.required && !value.trim()) return requiredError(field);\n if ((field.type === \"shortText\" || field.type === \"longText\") && field.maxLength !== undefined && value.length > field.maxLength) {\n return `Enter no more than ${field.maxLength} characters.`;\n }\n}\n\nfunction richTextError(field: FormField, value: unknown): string | undefined {\n const error = documentError(value);\n if (error) return error;\n if (field.required && !hasRichText(value as RichTextDocument)) return requiredError(field);\n}\n\nfunction choiceError(field: FormField, value: unknown): string | undefined {\n if (typeof value !== \"string\") return \"Choose an available option.\";\n if (value === \"\") return field.required ? requiredError(field) : undefined;\n // An empty list means the choices are still loading, so a stored value stays valid until they arrive.\n if (field.type === \"select\" && field.options.length > 0 && !field.options.some((option) => option.value === value)) {\n return \"Choose an available option.\";\n }\n}\n\nfunction linkError(field: FormField, value: unknown): string | undefined {\n if (field.type !== \"asset\" && field.type !== \"reference\") return;\n const { key, itemLabel, itemsLabel } = linkCopy[field.type];\n if (!field.multiple) return isLink(value, key) ? undefined : `Choose an ${itemLabel}.`;\n if (!Array.isArray(value) || !value.every((item) => isLink(item, key))) return `Choose a list of ${itemsLabel}.`;\n if (field.required && value.length === 0) return requiredError(field);\n const max = field.picker?.max;\n if (max !== undefined && value.length > max) return `Choose no more than ${max} ${pickerCopy(field).itemsLabel}.`;\n}\n\nconst validators: Record<FormField[\"type\"], (field: FormField, value: unknown) => string | undefined> = {\n shortText: textError,\n longText: textError,\n richText: richTextError,\n number: (field, value) => {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return \"Enter a finite number.\";\n if (field.type !== \"number\") return;\n if (field.min !== undefined && value < field.min) return `Enter a number of at least ${field.min}.`;\n if (field.max !== undefined && value > field.max) return `Enter a number no greater than ${field.max}.`;\n },\n boolean: (_field, value) => typeof value === \"boolean\" ? undefined : \"Choose a boolean value.\",\n dateTime: (_field, value) => parseUtcDateTime(value) ? undefined : \"Enter a valid UTC date and time.\",\n select: choiceError,\n asset: linkError,\n reference: linkError,\n};\n\nexport function fieldError(field: FormField, value: unknown): string | undefined {\n if (value === undefined) return field.required ? requiredError(field) : undefined;\n return validators[field.type](field, value);\n}\n\n/** Validate data loaded from JSON as well as values emitted by FormEditor. */\nexport function validateFormValues(model: FormSchema, values: Record<string, unknown>): FormErrors {\n assertModel(model);\n return Object.fromEntries(model.fields.flatMap((field): [string, string][] => {\n const error = fieldError(field, Object.hasOwn(values, field.id) ? values[field.id] : undefined);\n return error ? [[field.id, error]] : [];\n }));\n}\n","import { EntryPicker, type EntryItem } from \"../EntryPicker\";\nimport type { FieldProps } from \"../Field\";\nimport { NumberField } from \"../NumberField\";\nimport { RichTextEditor, type RichTextDocument } from \"../RichTextEditor\";\nimport { emptyDocument } from \"../RichTextEditor/document\";\nimport { Select } from \"../Select\";\nimport { Switch } from \"../Switch\";\nimport { TextArea, TextField } from \"../TextField\";\nimport { parseUtcDateTime, pickerCopy, type FieldOf, type FormField, type FormFieldValue } from \"./model\";\n\nfunction selectedIds(field: FormField, value: FormFieldValue | undefined): string[] {\n const key = field.type === \"asset\" ? \"assetId\" : \"entryId\";\n const links = Array.isArray(value) ? value : value === undefined ? [] : [value];\n return links.flatMap((link) => {\n if (!link || typeof link !== \"object\" || !(key in link)) return [];\n const id = (link as unknown as Record<string, unknown>)[key];\n return typeof id === \"string\" ? [id] : [];\n });\n}\n\nfunction pickerValue(field: FormField, ids: string[]): FormFieldValue | undefined {\n if (field.type === \"asset\") {\n const links = ids.map((assetId) => ({ assetId }));\n return field.multiple ? links : links[0];\n }\n const links = ids.map((entryId) => ({ entryId }));\n return field.multiple ? links : links[0];\n}\n\ntype Accessibility = Parameters<FieldProps[\"children\"]>[0];\n\ninterface ControlProps<F extends FormField> {\n field: F;\n stored: FormFieldValue | undefined;\n isDisabled: boolean;\n required: boolean | undefined;\n accessibility: Omit<Accessibility, \"required\">;\n onChange: (value: FormFieldValue | undefined) => void;\n}\n\nfunction NumberControl({ field, stored, isDisabled, required, accessibility, onChange }: ControlProps<FieldOf<\"number\">>) {\n return <NumberField {...accessibility} required={required} isDisabled={isDisabled} placeholder={field.placeholder}\n min={field.min} max={field.max} step={field.step ?? \"any\"} hasSteppers={field.hasSteppers ?? false} autoFocus={field.autoFocus}\n decreaseLabel={`Decrease ${field.label}`} increaseLabel={`Increase ${field.label}`}\n value={typeof stored === \"number\" && Number.isFinite(stored) ? stored : \"\"}\n onValueChange={(next) => { if (next === \"\" || Number.isFinite(next)) onChange(next === \"\" ? undefined : next); }} />;\n}\n\nfunction SelectControl({ field, stored, isDisabled, required, accessibility, onChange }: ControlProps<FieldOf<\"select\">>) {\n // Optional selects lead with an empty choice; picking it removes the key.\n const isClearable = !required && !field.options.some((option) => option.value === \"\");\n return <Select {...accessibility} aria-required={required || undefined} isDisabled={isDisabled} isInvalid={accessibility[\"aria-invalid\"]}\n options={isClearable ? [{ value: \"\", label: field.placeholder ?? \"None\" }, ...field.options] : field.options}\n placeholder={field.placeholder} autoFocus={field.autoFocus}\n value={typeof stored === \"string\" ? stored : \"\"} onValueChange={(next) => onChange(next === \"\" ? undefined : next)} />;\n}\n\nfunction PickerControl({ field, stored, items, isDisabled, accessibility, onChange }: ControlProps<FieldOf<\"asset\" | \"reference\">> & { items: EntryItem[] }) {\n return <div {...accessibility} role=\"group\">\n <EntryPicker items={items} value={selectedIds(field, stored)}\n {...pickerCopy(field)} mode={field.multiple ? \"multiple\" : \"single\"} isDisabled={isDisabled}\n onValueChange={(ids) => onChange(pickerValue(field, ids))} />\n </div>;\n}\n\ninterface FormControlProps {\n field: FormField;\n stored: FormFieldValue | undefined;\n items: EntryItem[];\n isDisabled: boolean;\n accessibility: Accessibility;\n onChange: (value: FormFieldValue | undefined) => void;\n}\n\nexport function FormControl({ field, stored, items, isDisabled, accessibility: { required, ...accessibility }, onChange }: FormControlProps) {\n const shared = { stored, isDisabled, required, accessibility, onChange };\n switch (field.type) {\n case \"shortText\":\n return <TextField {...accessibility} required={required} disabled={isDisabled} placeholder={field.placeholder}\n type={field.inputType} maxLength={field.maxLength} readOnly={field.readOnly} autoFocus={field.autoFocus}\n value={typeof stored === \"string\" ? stored : \"\"} onChange={(event) => onChange(event.target.value)} />;\n case \"longText\":\n return <TextArea {...accessibility} required={required} disabled={isDisabled} placeholder={field.placeholder}\n rows={field.rows} maxLength={field.maxLength} readOnly={field.readOnly} autoFocus={field.autoFocus}\n value={typeof stored === \"string\" ? stored : \"\"} onChange={(event) => onChange(event.target.value)} />;\n case \"number\":\n return <NumberControl field={field} {...shared} />;\n case \"boolean\":\n return <Switch {...accessibility} isDisabled={isDisabled} autoFocus={field.autoFocus} isSelected={stored === true} onSelectedChange={onChange} />;\n case \"dateTime\":\n return <TextField {...accessibility} required={required} disabled={isDisabled} type=\"datetime-local\" step=\"0.001\" autoFocus={field.autoFocus}\n value={parseUtcDateTime(stored)?.slice(0, -1) ?? \"\"}\n onChange={(event) => onChange(parseUtcDateTime(`${event.target.value}Z`))} />;\n case \"richText\":\n return <RichTextEditor {...accessibility} label={field.label} isRequired={required} isDisabled={isDisabled}\n placeholder={field.placeholder} format=\"json\" value={stored === undefined ? emptyDocument : stored as RichTextDocument}\n onChange={onChange} />;\n case \"select\":\n return <SelectControl field={field} {...shared} />;\n case \"asset\":\n case \"reference\":\n return <PickerControl field={field} items={items} {...shared} />;\n }\n}\n","import { useMemo, useState, type CSSProperties, type HTMLAttributes } from \"react\";\nimport type { EntryItem } from \"../EntryPicker\";\nimport { Field } from \"../Field\";\nimport type { GridColumns } from \"../Grid\";\nimport { FormControl } from \"./control\";\nimport { assertModel, fieldError, type FormField, type FormSchema, type FormErrors, type FormFieldValue, type FormValues } from \"./model\";\nimport \"./style.css\";\n\nexport { validateFormValues } from \"./model\";\nexport type { AssetValue, FormField, FormSchema, FormErrors, FormFieldValue, FormValues, ReferenceValue } from \"./model\";\n\nexport interface FormChange { fieldId: string }\n\nexport interface FormEditorProps extends Omit<HTMLAttributes<HTMLDivElement>, \"defaultValue\" | \"onChange\"> {\n schema: FormSchema;\n value?: FormValues;\n defaultValue?: FormValues;\n onValueChange?: (values: FormValues, change: FormChange) => void;\n /** Available assets or entries, keyed by field ID. Loading belongs to the app. */\n pickerItems?: Record<string, EntryItem[]>;\n /** App-provided messages take precedence over built-in validation. */\n errors?: FormErrors;\n isDisabled?: boolean;\n showAllErrors?: boolean;\n /** Columns at the widest. The form drops one whenever a field would be narrower than `minColumnWidth`. */\n columns?: GridColumns;\n /** Narrowest a field may get before the form drops a column. */\n minColumnWidth?: string;\n}\n\ninterface FormEditorFieldProps {\n field: FormField;\n stored: FormFieldValue | undefined;\n items: EntryItem[];\n isDisabled: boolean;\n error: string | undefined;\n isErrorVisible: boolean;\n onChange: (value: FormFieldValue | undefined) => void;\n}\n\n/** Validates only when its message can show, and only when its own field or value changes. */\nfunction FormEditorField({ field, stored, items, isDisabled, error, isErrorVisible, onChange }: FormEditorFieldProps) {\n const validation = useMemo(() => error === undefined && isErrorVisible ? fieldError(field, stored) : undefined,\n [error, isErrorVisible, field, stored]);\n const label = field.type === \"dateTime\" ? `${field.label} (UTC)` : field.label;\n return (\n <Field label={label} hint={field.hint} error={error ?? validation} isRequired={field.required}\n isGroup={field.type === \"asset\" || field.type === \"reference\"}>\n {(accessibility) => <FormControl field={field} stored={stored} items={items}\n isDisabled={isDisabled} accessibility={accessibility} onChange={onChange} />}\n </Field>\n );\n}\n\n/** Ordered form controls. Loading, submission, and persistence belong to the app. */\nexport function FormEditor({ schema, value, defaultValue = {}, onValueChange, pickerItems = {}, errors = {},\n isDisabled = false, showAllErrors = false, columns = 1, minColumnWidth = \"16rem\", className, style, ...rest }: FormEditorProps) {\n const [internal, setInternal] = useState<FormValues>(defaultValue);\n const [changed, setChanged] = useState<Set<string>>(() => new Set());\n const current = value ?? internal;\n useMemo(() => assertModel(schema), [schema]);\n\n const commit = (fieldId: string, next: FormFieldValue | undefined) => {\n const values = { ...current };\n if (next === undefined) delete values[fieldId];\n else values[fieldId] = next;\n if (value === undefined) setInternal(values);\n setChanged((previous) => new Set(previous).add(fieldId));\n onValueChange?.(values, { fieldId });\n };\n\n const layout = columns === \"auto\"\n ? { \"--form-editor-min-column\": minColumnWidth }\n : { \"--form-editor-columns\": columns, \"--form-editor-min-column\": minColumnWidth };\n\n return (\n <div className={[\"ds-form-editor\", columns === \"auto\" && \"ds-form-editor--auto\", className].filter(Boolean).join(\" \")}\n style={{ ...layout, ...style } as CSSProperties} {...rest}>\n {schema.fields.map((field) => {\n const stored = Object.hasOwn(current, field.id) ? current[field.id] : undefined;\n const fieldDisabled = isDisabled || Boolean(field.isDisabled);\n const isLocked = fieldDisabled || (\"readOnly\" in field && Boolean(field.readOnly));\n // NumberField marks an out-of-range number invalid itself, so its message shows straight away.\n const isErrorVisible = showAllErrors || changed.has(field.id) || (field.type === \"number\" && typeof stored === \"number\");\n return <FormEditorField key={field.id} field={field} stored={stored} items={pickerItems[field.id] ?? []}\n isDisabled={fieldDisabled} error={errors[field.id]} isErrorVisible={isErrorVisible}\n onChange={(next) => { if (!isLocked) commit(field.id, next); }} />;\n })}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../Button/index.cjs"),t=require("../Drawer/index.cjs"),n=require("../SideNav/index.cjs"),r=require("../TopNav/index.cjs");let i=require("react"),a=require("react/jsx-runtime");var o=(0,i.forwardRef)(function({brand:o,navigation:s,actions:c,navigationLabel:l=`Main`,className:u,children:d,...f},p){let[m,h]=(0,i.useState)(null),[g,_]=(0,i.useState)(!1),v=(0,i.useRef)(null),y=(0,i.useRef)(null),b=(0,i.useRef)(!1),x=(0,i.useId)(),S=(0,i.useCallback)(e=>{h(e),typeof p==`function`?p(e):p&&(p.current=e)},[p]);(0,i.useEffect)(()=>{if(!m)return;let e=e=>{e<768||(m.querySelector(`[data-state='open'] [role='dialog']`)?.contains(document.activeElement)&&(b.current=!0),_(!1))};if(e(m.getBoundingClientRect().width),typeof ResizeObserver>`u`)return;let t=new ResizeObserver(([t])=>{t&&e(t.contentRect.width)});return t.observe(m),()=>{t.disconnect()}},[m]),(0,i.useEffect)(()=>{!g&&b.current&&(b.current=!1,(v.current?.querySelector(`[aria-current='page']`)??v.current?.querySelector(`a[href]`)??y.current)?.focus())},[g]);let C=c?.(`drawer`);return(0,a.jsxs)(`div`,{...f,ref:S,className:[`ds-appshell`,u].filter(Boolean).join(` `),children:[(0,a.jsxs)(`div`,{className:`ds-appshell__frame`,"aria-hidden":g||void 0,ref:e=>{e&&(e.inert=g)},children:[(0,a.jsx)(r.TopNav,{brand:o,actions:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(`div`,{className:`ds-appshell__actions`,children:c?.(`topnav`)}),(0,a.jsx)(e.Button,{variant:`simple`,size:`lg`,isIconOnly:!0,iconStart:`menu`,className:`ds-appshell__toggle`,"aria-label":`Open navigation`,"aria-expanded":g,"aria-controls":x,onClick:()=>_(!0)})]})}),(0,a.jsxs)(`div`,{className:`ds-appshell__body`,children:[(0,a.jsx)(n.SideNav,{ref:v,className:`ds-appshell__desktop-nav`,label:l,children:s}),(0,a.jsx)(`main`,{ref:y,className:`ds-appshell__main`,tabIndex:-1,children:d})]})]}),(0,a.jsx)(t.Drawer,{id:x,isOpen:g,onClose:()=>_(!1),variant:`navigation`,portalContainer:m,title:o,"aria-label":`Navigation`,closeLabel:`Close navigation`,footer:C?(0,a.jsx)(n.SideNavFooter,{children:C}):void 0,children:(0,a.jsx)(n.SideNav,{className:`ds-appshell__mobile-nav`,label:l,onClick:e=>{let t=e.target instanceof Element?e.target.closest(`a[href]`):null,n=e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey||t?.target===`_blank`;t&&!n&&_(!1)},children:s})})]})});exports.AppShell=o;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../Button/index.cjs"),t=require("../Drawer/index.cjs"),n=require("../SideNav/index.cjs"),r=require("../TopNav/index.cjs");let i=require("react"),a=require("react/jsx-runtime");var o=(0,i.forwardRef)(function({brand:o,navigation:s,actions:c,navigationLabel:l=`Main`,className:u,children:d,...f},p){let[m,h]=(0,i.useState)(null),[g,_]=(0,i.useState)(!1),v=(0,i.useRef)(null),y=(0,i.useRef)(null),b=(0,i.useRef)(!1),x=(0,i.useId)(),S=(0,i.useCallback)(e=>{h(e),typeof p==`function`?p(e):p&&(p.current=e)},[p]);(0,i.useEffect)(()=>{if(!m)return;let e=e=>{e<768||(m.querySelector(`[data-state='open'] [role='dialog']`)?.contains(document.activeElement)&&(b.current=!0),_(!1))};if(e(m.getBoundingClientRect().width),typeof ResizeObserver>`u`)return;let t=new ResizeObserver(([t])=>{t&&e(t.contentRect.width)});return t.observe(m),()=>{t.disconnect()}},[m]),(0,i.useEffect)(()=>{!g&&b.current&&(b.current=!1,(v.current?.querySelector(`[aria-current='page']`)??v.current?.querySelector(`a[href]`)??y.current)?.focus())},[g]);let C=c?.(`drawer`);return(0,a.jsxs)(`div`,{...f,ref:S,className:[`ds-appshell`,u].filter(Boolean).join(` `),children:[(0,a.jsxs)(`div`,{className:`ds-appshell__frame`,"aria-hidden":g||void 0,ref:e=>{e&&(e.inert=g)},children:[(0,a.jsx)(r.TopNav,{brand:o,actions:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(`div`,{className:`ds-appshell__actions`,children:c?.(`topnav`)}),(0,a.jsx)(e.Button,{variant:`simple`,size:`lg`,isIconOnly:!0,iconStart:`menu`,className:`ds-appshell__toggle`,"aria-label":`Open navigation`,"aria-expanded":g,"aria-controls":x,onClick:()=>_(!0)})]})}),(0,a.jsxs)(`div`,{className:`ds-appshell__body`,children:[(0,a.jsx)(n.SideNav,{ref:v,className:`ds-appshell__desktop-nav`,label:l,children:s}),(0,a.jsx)(`main`,{ref:y,className:`ds-appshell__main`,tabIndex:-1,children:d})]})]}),(0,a.jsx)(t.Drawer,{id:x,isOpen:g,onClose:()=>_(!1),variant:`navigation`,side:`end`,portalContainer:m,title:o,"aria-label":`Navigation`,closeLabel:`Close navigation`,footer:C?(0,a.jsx)(n.SideNavFooter,{children:C}):void 0,children:(0,a.jsx)(n.SideNav,{className:`ds-appshell__mobile-nav`,label:l,onClick:e=>{let t=e.target instanceof Element?e.target.closest(`a[href]`):null,n=e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey||t?.target===`_blank`;t&&!n&&_(!1)},children:s})})]})});exports.AppShell=o;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["forwardRef","useState","useRef","useId","useCallback","TopNav","_Fragment","Button","SideNav","Drawer","SideNavFooter","require_components_Button_index","require_components_Drawer_index","require_components_SideNav_index","require_components_TopNav_index","react","react_jsx_runtime","AppShell","rest","shell","setShell","isOpen","setOpen","desktopNavRef","mainRef","restoreDesktopFocus","drawerId","shellRef","node","ref","measure","width","observer","entry","drawerActions","actions","className","navigationLabel","navigation","brand","link","event","opensElsewhere"],"sources":["../../../src/components/AppShell/index.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { Drawer } from \"../Drawer\";\nimport { Button } from \"../Button\";\nimport { SideNav, SideNavFooter } from \"../SideNav\";\nimport { TopNav } from \"../TopNav\";\nimport \"./style.css\";\n\nexport interface AppShellProps extends HTMLAttributes<HTMLDivElement> {\n /** Product brand, shared by the top bar and mobile drawer header. */\n brand: ReactNode;\n /** SideNavSection/SideNavItem content. The application owns routing and selection. */\n navigation: ReactNode;\n /** One slot with a compact top-bar and expanded drawer presentation. */\n actions?: (location: \"topnav\" | \"drawer\") => ReactNode;\n navigationLabel?: string;\n /** Rendered inside the shell's scrolling main landmark. */\n children?: ReactNode;\n}\n\n/** Full-width product bar above a desktop rail, or a mobile navigation drawer. */\nexport const AppShell = forwardRef<HTMLDivElement, AppShellProps>(function AppShell(\n { brand, navigation, actions, navigationLabel = \"Main\", className, children, ...rest },\n ref,\n) {\n const [shell, setShell] = useState<HTMLDivElement | null>(null);\n const [isOpen, setOpen] = useState(false);\n const desktopNavRef = useRef<HTMLElement | null>(null);\n const mainRef = useRef<HTMLElement | null>(null);\n const restoreDesktopFocus = useRef(false);\n const drawerId = useId();\n const shellRef = useCallback((node: HTMLDivElement | null) => {\n setShell(node);\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n }, [ref]);\n\n useEffect(() => {\n if (!shell) return;\n const measure = (width: number) => {\n if (width < 768) return;\n const focusInDrawer = shell.querySelector(\"[data-state='open'] [role='dialog']\")?.contains(document.activeElement);\n if (focusInDrawer) restoreDesktopFocus.current = true;\n setOpen(false);\n };\n measure(shell.getBoundingClientRect().width);\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(([entry]) => {\n if (entry) measure(entry.contentRect.width);\n });\n observer.observe(shell);\n return () => {\n observer.disconnect();\n };\n }, [shell]);\n\n useEffect(() => {\n if (isOpen || !restoreDesktopFocus.current) return;\n restoreDesktopFocus.current = false;\n const destination = desktopNavRef.current?.querySelector<HTMLElement>(\"[aria-current='page']\")\n ?? desktopNavRef.current?.querySelector<HTMLElement>(\"a[href]\");\n (destination ?? mainRef.current)?.focus();\n }, [isOpen]);\n\n const drawerActions = actions?.(\"drawer\");\n\n return (\n <div {...rest} ref={shellRef} className={[\"ds-appshell\", className].filter(Boolean).join(\" \")}>\n <div\n className=\"ds-appshell__frame\"\n aria-hidden={isOpen || undefined}\n ref={(node) => { if (node) node.inert = isOpen; }}\n >\n <TopNav\n brand={brand}\n actions={<>\n <div className=\"ds-appshell__actions\">{actions?.(\"topnav\")}</div>\n <Button\n variant=\"simple\"\n size=\"lg\"\n isIconOnly\n iconStart=\"menu\"\n className=\"ds-appshell__toggle\"\n aria-label=\"Open navigation\"\n aria-expanded={isOpen}\n aria-controls={drawerId}\n onClick={() => setOpen(true)}\n />\n </>}\n />\n <div className=\"ds-appshell__body\">\n <SideNav ref={desktopNavRef} className=\"ds-appshell__desktop-nav\" label={navigationLabel}>\n {navigation}\n </SideNav>\n <main ref={mainRef} className=\"ds-appshell__main\" tabIndex={-1}>{children}</main>\n </div>\n </div>\n <Drawer\n id={drawerId}\n isOpen={isOpen}\n onClose={() => setOpen(false)}\n variant=\"navigation\"\n portalContainer={shell}\n title={brand}\n aria-label=\"Navigation\"\n closeLabel=\"Close navigation\"\n footer={drawerActions ? <SideNavFooter>{drawerActions}</SideNavFooter> : undefined}\n >\n <SideNav\n className=\"ds-appshell__mobile-nav\"\n label={navigationLabel}\n onClick={(event) => {\n const link = event.target instanceof Element ? event.target.closest<HTMLAnchorElement>(\"a[href]\") : null;\n // Opening a link elsewhere (modifier keys, another button, a new tab) leaves this page in place.\n const opensElsewhere = event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey\n || event.altKey || link?.target === \"_blank\";\n if (link && !opensElsewhere) setOpen(false);\n }}\n >\n {navigation}\n </SideNav>\n </Drawer>\n </div>\n );\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["forwardRef","useState","useRef","useId","useCallback","TopNav","_Fragment","Button","SideNav","Drawer","SideNavFooter","require_components_Button_index","require_components_Drawer_index","require_components_SideNav_index","require_components_TopNav_index","react","react_jsx_runtime","AppShell","rest","shell","setShell","isOpen","setOpen","desktopNavRef","mainRef","restoreDesktopFocus","drawerId","shellRef","node","ref","measure","width","observer","entry","drawerActions","actions","className","navigationLabel","navigation","brand","link","event","opensElsewhere"],"sources":["../../../src/components/AppShell/index.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { Drawer } from \"../Drawer\";\nimport { Button } from \"../Button\";\nimport { SideNav, SideNavFooter } from \"../SideNav\";\nimport { TopNav } from \"../TopNav\";\nimport \"./style.css\";\n\nexport interface AppShellProps extends HTMLAttributes<HTMLDivElement> {\n /** Product brand, shared by the top bar and mobile drawer header. */\n brand: ReactNode;\n /** SideNavSection/SideNavItem content. The application owns routing and selection. */\n navigation: ReactNode;\n /** One slot with a compact top-bar and expanded drawer presentation. */\n actions?: (location: \"topnav\" | \"drawer\") => ReactNode;\n navigationLabel?: string;\n /** Rendered inside the shell's scrolling main landmark. */\n children?: ReactNode;\n}\n\n/** Full-width product bar above a desktop rail, or a mobile navigation drawer. */\nexport const AppShell = forwardRef<HTMLDivElement, AppShellProps>(function AppShell(\n { brand, navigation, actions, navigationLabel = \"Main\", className, children, ...rest },\n ref,\n) {\n const [shell, setShell] = useState<HTMLDivElement | null>(null);\n const [isOpen, setOpen] = useState(false);\n const desktopNavRef = useRef<HTMLElement | null>(null);\n const mainRef = useRef<HTMLElement | null>(null);\n const restoreDesktopFocus = useRef(false);\n const drawerId = useId();\n const shellRef = useCallback((node: HTMLDivElement | null) => {\n setShell(node);\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n }, [ref]);\n\n useEffect(() => {\n if (!shell) return;\n const measure = (width: number) => {\n if (width < 768) return;\n const focusInDrawer = shell.querySelector(\"[data-state='open'] [role='dialog']\")?.contains(document.activeElement);\n if (focusInDrawer) restoreDesktopFocus.current = true;\n setOpen(false);\n };\n measure(shell.getBoundingClientRect().width);\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(([entry]) => {\n if (entry) measure(entry.contentRect.width);\n });\n observer.observe(shell);\n return () => {\n observer.disconnect();\n };\n }, [shell]);\n\n useEffect(() => {\n if (isOpen || !restoreDesktopFocus.current) return;\n restoreDesktopFocus.current = false;\n const destination = desktopNavRef.current?.querySelector<HTMLElement>(\"[aria-current='page']\")\n ?? desktopNavRef.current?.querySelector<HTMLElement>(\"a[href]\");\n (destination ?? mainRef.current)?.focus();\n }, [isOpen]);\n\n const drawerActions = actions?.(\"drawer\");\n\n return (\n <div {...rest} ref={shellRef} className={[\"ds-appshell\", className].filter(Boolean).join(\" \")}>\n <div\n className=\"ds-appshell__frame\"\n aria-hidden={isOpen || undefined}\n ref={(node) => { if (node) node.inert = isOpen; }}\n >\n <TopNav\n brand={brand}\n actions={<>\n <div className=\"ds-appshell__actions\">{actions?.(\"topnav\")}</div>\n <Button\n variant=\"simple\"\n size=\"lg\"\n isIconOnly\n iconStart=\"menu\"\n className=\"ds-appshell__toggle\"\n aria-label=\"Open navigation\"\n aria-expanded={isOpen}\n aria-controls={drawerId}\n onClick={() => setOpen(true)}\n />\n </>}\n />\n <div className=\"ds-appshell__body\">\n <SideNav ref={desktopNavRef} className=\"ds-appshell__desktop-nav\" label={navigationLabel}>\n {navigation}\n </SideNav>\n <main ref={mainRef} className=\"ds-appshell__main\" tabIndex={-1}>{children}</main>\n </div>\n </div>\n <Drawer\n id={drawerId}\n isOpen={isOpen}\n onClose={() => setOpen(false)}\n variant=\"navigation\"\n side=\"end\"\n portalContainer={shell}\n title={brand}\n aria-label=\"Navigation\"\n closeLabel=\"Close navigation\"\n footer={drawerActions ? <SideNavFooter>{drawerActions}</SideNavFooter> : undefined}\n >\n <SideNav\n className=\"ds-appshell__mobile-nav\"\n label={navigationLabel}\n onClick={(event) => {\n const link = event.target instanceof Element ? event.target.closest<HTMLAnchorElement>(\"a[href]\") : null;\n // Opening a link elsewhere (modifier keys, another button, a new tab) leaves this page in place.\n const opensElsewhere = event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey\n || event.altKey || link?.target === \"_blank\";\n if (link && !opensElsewhere) setOpen(false);\n }}\n >\n {navigation}\n </SideNav>\n </Drawer>\n </div>\n );\n});\n"],"mappings":"A,oQA6BA,IAAaiB,GAAA,EAAWjB,EAAAA,WAAAA,CAA0C,SAChE,CAAE,QAAO,aAAY,UAAS,kBAAkB,OAAQ,YAAW,WAAU,GAAGkB,GAChF,EACA,CACA,GAAM,CAACC,EAAOC,IAAA,EAAYnB,EAAAA,SAAAA,CAAgC,IAAI,EACxD,CAACoB,EAAQC,IAAA,EAAWrB,EAAAA,SAAAA,CAAS,EAAK,EAClCsB,GAAA,EAAgBrB,EAAAA,OAAAA,CAA2B,IAAI,EAC/CsB,GAAA,EAAUtB,EAAAA,OAAAA,CAA2B,IAAI,EACzCuB,GAAA,EAAsBvB,EAAAA,OAAAA,CAAO,EAAK,EAClCwB,GAAA,EAAWvB,EAAAA,MAAAA,CAAM,EACjBwB,GAAA,EAAWvB,EAAAA,YAAAA,CAAa,GAAgC,CAC5DgB,EAASQ,CAAI,EACT,OAAOC,GAAQ,WAAYA,EAAID,CAAI,EAC9BC,IAAK,EAAI,QAAUD,EAC9B,EAAG,CAACC,CAAG,CAAC,GAER,EAAAd,EAAA,UAAA,KAAgB,CACd,GAAI,CAACI,EAAO,OACZ,IAAMW,EAAW,GAAkB,CAC7BC,EAAQ,MACUZ,EAAM,cAAc,qCAAqC,CAAC,EAAE,SAAS,SAAS,aAAa,IAC9F,EAAoB,QAAU,IACjDG,EAAQ,EAAK,EACf,EAEA,GADAQ,EAAQX,EAAM,sBAAsB,CAAC,CAAC,KAAK,EACvC,OAAO,eAAmB,IAAa,OAC3C,IAAMa,EAAW,IAAI,gBAAgB,CAACC,KAAW,CAC3CA,GAAOH,EAAQG,EAAM,YAAY,KAAK,CAC5C,CAAC,EAED,OADAD,EAAS,QAAQb,CAAK,MACT,CACXa,EAAS,WAAW,CACtB,CACF,EAAG,CAACb,CAAK,CAAC,GAEV,EAAAJ,EAAA,UAAA,KAAgB,CACV,IAAWU,EAAoB,UACnC,EAAoB,QAAU,IACVF,EAAc,SAAS,cAA2B,uBAAuB,GACxFA,EAAc,SAAS,cAA2B,SAAS,GAChDC,EAAQ,QAAA,EAAU,MAAM,EAC1C,EAAG,CAACH,CAAM,CAAC,EAEX,IAAMa,EAAgBC,IAAU,QAAQ,EAExC,OACE,EAAAnB,EAAA,KAAA,CAAC,MAAD,CAAK,GAAIE,EAAM,IAAKS,EAAU,UAAW,CAAC,cAAeS,CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EAA5F,SAAA,EACE,EAAApB,EAAA,KAAA,CAAC,MAAD,CACE,UAAU,qBACV,cAAaK,GAAU,IAAA,GACvB,IAAM,GAAS,CAAMO,IAAM,EAAK,MAAQP,EAAQ,EAHlD,SAAA,EAKE,EAAAL,EAAA,IAAA,CAACX,EAAAA,OAAD,CACS,QACP,SAAS,EAAAW,EAAA,KAAA,CAAAV,EAAAA,SAAA,CAAA,SAAA,EACP,EAAAU,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,uBAAwB,SAAAmB,IAAU,QAAQ,CAAO,CAAA,GAChE,EAAAnB,EAAA,IAAA,CAACT,EAAAA,OAAD,CACE,QAAQ,SACR,KAAK,KACL,WAAA,GACA,UAAU,OACV,UAAU,sBACV,aAAW,kBACX,gBAAec,EACf,gBAAeK,EACf,YAAeJ,EAAQ,EAAI,CAC5B,CAAA,CACD,CAAA,CAAA,CACH,CAAA,GACD,EAAAN,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,oBAAf,SAAA,EACE,EAAAA,EAAA,IAAA,CAACR,EAAAA,QAAD,CAAS,IAAKe,EAAe,UAAU,2BAA2B,MAAOc,EACtE,SAAAC,CACM,CAAA,GACT,EAAAtB,EAAA,IAAA,CAAC,OAAD,CAAM,IAAKQ,EAAS,UAAU,oBAAoB,SAAU,GAAK,UAAe,CAAA,CAC7E,CACF,CAAA,CAAA,CACL,CAAA,GAAA,EAAAR,EAAA,IAAA,CAACP,EAAAA,OAAD,CACE,GAAIiB,EACI,SACR,YAAeJ,EAAQ,EAAK,EAC5B,QAAQ,aACR,KAAK,MACL,gBAAiBH,EACjB,MAAOoB,EACP,aAAW,aACX,WAAW,mBACX,OAAQL,GAAgB,EAAAlB,EAAA,IAAA,CAACN,EAAAA,cAAD,CAAA,SAAgBwB,CAA6B,CAAA,EAAI,IAAA,GAEzE,UAAA,EAAAlB,EAAA,IAAA,CAACR,EAAAA,QAAD,CACE,UAAU,0BACV,MAAO6B,EACP,QAAU,GAAU,CAClB,IAAMG,EAAOC,EAAM,kBAAkB,QAAUA,EAAM,OAAO,QAA2B,SAAS,EAAI,KAE9FC,EAAiBD,EAAM,SAAW,GAAKA,EAAM,SAAWA,EAAM,SAAWA,EAAM,UAChFA,EAAM,QAAUD,GAAM,SAAW,SAClCA,GAAQ,CAACE,GAAgBpB,EAAQ,EAAK,CAC5C,EAEC,SAAAgB,CACM,CAAA,CACH,CAAA,CACL,C,EAET,CAAC,E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../src/components/AppShell/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAKf,OAAO,aAAa,CAAC;AAErB,MAAM,WAAW,aAAc,SAAQ,cAAc,CAAC,cAAc,CAAC;IACnE,qEAAqE;IACrE,KAAK,EAAE,SAAS,CAAC;IACjB,sFAAsF;IACtF,UAAU,EAAE,SAAS,CAAC;IACtB,wEAAwE;IACxE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,KAAK,SAAS,CAAC;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,kFAAkF;AAClF,eAAO,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../src/components/AppShell/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAKf,OAAO,aAAa,CAAC;AAErB,MAAM,WAAW,aAAc,SAAQ,cAAc,CAAC,cAAc,CAAC;IACnE,qEAAqE;IACrE,KAAK,EAAE,SAAS,CAAC;IACjB,sFAAsF;IACtF,UAAU,EAAE,SAAS,CAAC;IACtB,wEAAwE;IACxE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,KAAK,SAAS,CAAC;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,kFAAkF;AAClF,eAAO,MAAM,QAAQ,0GAwGnB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/AppShell/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAKf,OAAO,aAAa,CAAC;AAErB,MAAM,WAAW,aAAc,SAAQ,cAAc,CAAC,cAAc,CAAC;IACnE,qEAAqE;IACrE,KAAK,EAAE,SAAS,CAAC;IACjB,sFAAsF;IACtF,UAAU,EAAE,SAAS,CAAC;IACtB,wEAAwE;IACxE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,KAAK,SAAS,CAAC;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,kFAAkF;AAClF,eAAO,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/AppShell/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAKf,OAAO,aAAa,CAAC;AAErB,MAAM,WAAW,aAAc,SAAQ,cAAc,CAAC,cAAc,CAAC;IACnE,qEAAqE;IACrE,KAAK,EAAE,SAAS,CAAC;IACjB,sFAAsF;IACtF,UAAU,EAAE,SAAS,CAAC;IACtB,wEAAwE;IACxE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,KAAK,SAAS,CAAC;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,kFAAkF;AAClF,eAAO,MAAM,QAAQ,0GAwGnB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_Fragment","Fragment$1","AppShell","forwardRef","rest","shell","setShell","useState","isOpen","setOpen","desktopNavRef","useRef","mainRef","restoreDesktopFocus","drawerId","useId","shellRef","useCallback","node","ref","useEffect","measure","width","observer","entry","drawerActions","actions","className","TopNav","Button","SideNav","navigationLabel","navigation","Drawer","brand","SideNavFooter","link","event","opensElsewhere"],"sources":["../../../src/components/AppShell/index.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { Drawer } from \"../Drawer\";\nimport { Button } from \"../Button\";\nimport { SideNav, SideNavFooter } from \"../SideNav\";\nimport { TopNav } from \"../TopNav\";\nimport \"./style.css\";\n\nexport interface AppShellProps extends HTMLAttributes<HTMLDivElement> {\n /** Product brand, shared by the top bar and mobile drawer header. */\n brand: ReactNode;\n /** SideNavSection/SideNavItem content. The application owns routing and selection. */\n navigation: ReactNode;\n /** One slot with a compact top-bar and expanded drawer presentation. */\n actions?: (location: \"topnav\" | \"drawer\") => ReactNode;\n navigationLabel?: string;\n /** Rendered inside the shell's scrolling main landmark. */\n children?: ReactNode;\n}\n\n/** Full-width product bar above a desktop rail, or a mobile navigation drawer. */\nexport const AppShell = forwardRef<HTMLDivElement, AppShellProps>(function AppShell(\n { brand, navigation, actions, navigationLabel = \"Main\", className, children, ...rest },\n ref,\n) {\n const [shell, setShell] = useState<HTMLDivElement | null>(null);\n const [isOpen, setOpen] = useState(false);\n const desktopNavRef = useRef<HTMLElement | null>(null);\n const mainRef = useRef<HTMLElement | null>(null);\n const restoreDesktopFocus = useRef(false);\n const drawerId = useId();\n const shellRef = useCallback((node: HTMLDivElement | null) => {\n setShell(node);\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n }, [ref]);\n\n useEffect(() => {\n if (!shell) return;\n const measure = (width: number) => {\n if (width < 768) return;\n const focusInDrawer = shell.querySelector(\"[data-state='open'] [role='dialog']\")?.contains(document.activeElement);\n if (focusInDrawer) restoreDesktopFocus.current = true;\n setOpen(false);\n };\n measure(shell.getBoundingClientRect().width);\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(([entry]) => {\n if (entry) measure(entry.contentRect.width);\n });\n observer.observe(shell);\n return () => {\n observer.disconnect();\n };\n }, [shell]);\n\n useEffect(() => {\n if (isOpen || !restoreDesktopFocus.current) return;\n restoreDesktopFocus.current = false;\n const destination = desktopNavRef.current?.querySelector<HTMLElement>(\"[aria-current='page']\")\n ?? desktopNavRef.current?.querySelector<HTMLElement>(\"a[href]\");\n (destination ?? mainRef.current)?.focus();\n }, [isOpen]);\n\n const drawerActions = actions?.(\"drawer\");\n\n return (\n <div {...rest} ref={shellRef} className={[\"ds-appshell\", className].filter(Boolean).join(\" \")}>\n <div\n className=\"ds-appshell__frame\"\n aria-hidden={isOpen || undefined}\n ref={(node) => { if (node) node.inert = isOpen; }}\n >\n <TopNav\n brand={brand}\n actions={<>\n <div className=\"ds-appshell__actions\">{actions?.(\"topnav\")}</div>\n <Button\n variant=\"simple\"\n size=\"lg\"\n isIconOnly\n iconStart=\"menu\"\n className=\"ds-appshell__toggle\"\n aria-label=\"Open navigation\"\n aria-expanded={isOpen}\n aria-controls={drawerId}\n onClick={() => setOpen(true)}\n />\n </>}\n />\n <div className=\"ds-appshell__body\">\n <SideNav ref={desktopNavRef} className=\"ds-appshell__desktop-nav\" label={navigationLabel}>\n {navigation}\n </SideNav>\n <main ref={mainRef} className=\"ds-appshell__main\" tabIndex={-1}>{children}</main>\n </div>\n </div>\n <Drawer\n id={drawerId}\n isOpen={isOpen}\n onClose={() => setOpen(false)}\n variant=\"navigation\"\n portalContainer={shell}\n title={brand}\n aria-label=\"Navigation\"\n closeLabel=\"Close navigation\"\n footer={drawerActions ? <SideNavFooter>{drawerActions}</SideNavFooter> : undefined}\n >\n <SideNav\n className=\"ds-appshell__mobile-nav\"\n label={navigationLabel}\n onClick={(event) => {\n const link = event.target instanceof Element ? event.target.closest<HTMLAnchorElement>(\"a[href]\") : null;\n // Opening a link elsewhere (modifier keys, another button, a new tab) leaves this page in place.\n const opensElsewhere = event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey\n || event.altKey || link?.target === \"_blank\";\n if (link && !opensElsewhere) setOpen(false);\n }}\n >\n {navigation}\n </SideNav>\n </Drawer>\n </div>\n );\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["_Fragment","Fragment$1","AppShell","forwardRef","rest","shell","setShell","useState","isOpen","setOpen","desktopNavRef","useRef","mainRef","restoreDesktopFocus","drawerId","useId","shellRef","useCallback","node","ref","useEffect","measure","width","observer","entry","drawerActions","actions","className","TopNav","Button","SideNav","navigationLabel","navigation","Drawer","brand","SideNavFooter","link","event","opensElsewhere"],"sources":["../../../src/components/AppShell/index.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { Drawer } from \"../Drawer\";\nimport { Button } from \"../Button\";\nimport { SideNav, SideNavFooter } from \"../SideNav\";\nimport { TopNav } from \"../TopNav\";\nimport \"./style.css\";\n\nexport interface AppShellProps extends HTMLAttributes<HTMLDivElement> {\n /** Product brand, shared by the top bar and mobile drawer header. */\n brand: ReactNode;\n /** SideNavSection/SideNavItem content. The application owns routing and selection. */\n navigation: ReactNode;\n /** One slot with a compact top-bar and expanded drawer presentation. */\n actions?: (location: \"topnav\" | \"drawer\") => ReactNode;\n navigationLabel?: string;\n /** Rendered inside the shell's scrolling main landmark. */\n children?: ReactNode;\n}\n\n/** Full-width product bar above a desktop rail, or a mobile navigation drawer. */\nexport const AppShell = forwardRef<HTMLDivElement, AppShellProps>(function AppShell(\n { brand, navigation, actions, navigationLabel = \"Main\", className, children, ...rest },\n ref,\n) {\n const [shell, setShell] = useState<HTMLDivElement | null>(null);\n const [isOpen, setOpen] = useState(false);\n const desktopNavRef = useRef<HTMLElement | null>(null);\n const mainRef = useRef<HTMLElement | null>(null);\n const restoreDesktopFocus = useRef(false);\n const drawerId = useId();\n const shellRef = useCallback((node: HTMLDivElement | null) => {\n setShell(node);\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n }, [ref]);\n\n useEffect(() => {\n if (!shell) return;\n const measure = (width: number) => {\n if (width < 768) return;\n const focusInDrawer = shell.querySelector(\"[data-state='open'] [role='dialog']\")?.contains(document.activeElement);\n if (focusInDrawer) restoreDesktopFocus.current = true;\n setOpen(false);\n };\n measure(shell.getBoundingClientRect().width);\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(([entry]) => {\n if (entry) measure(entry.contentRect.width);\n });\n observer.observe(shell);\n return () => {\n observer.disconnect();\n };\n }, [shell]);\n\n useEffect(() => {\n if (isOpen || !restoreDesktopFocus.current) return;\n restoreDesktopFocus.current = false;\n const destination = desktopNavRef.current?.querySelector<HTMLElement>(\"[aria-current='page']\")\n ?? desktopNavRef.current?.querySelector<HTMLElement>(\"a[href]\");\n (destination ?? mainRef.current)?.focus();\n }, [isOpen]);\n\n const drawerActions = actions?.(\"drawer\");\n\n return (\n <div {...rest} ref={shellRef} className={[\"ds-appshell\", className].filter(Boolean).join(\" \")}>\n <div\n className=\"ds-appshell__frame\"\n aria-hidden={isOpen || undefined}\n ref={(node) => { if (node) node.inert = isOpen; }}\n >\n <TopNav\n brand={brand}\n actions={<>\n <div className=\"ds-appshell__actions\">{actions?.(\"topnav\")}</div>\n <Button\n variant=\"simple\"\n size=\"lg\"\n isIconOnly\n iconStart=\"menu\"\n className=\"ds-appshell__toggle\"\n aria-label=\"Open navigation\"\n aria-expanded={isOpen}\n aria-controls={drawerId}\n onClick={() => setOpen(true)}\n />\n </>}\n />\n <div className=\"ds-appshell__body\">\n <SideNav ref={desktopNavRef} className=\"ds-appshell__desktop-nav\" label={navigationLabel}>\n {navigation}\n </SideNav>\n <main ref={mainRef} className=\"ds-appshell__main\" tabIndex={-1}>{children}</main>\n </div>\n </div>\n <Drawer\n id={drawerId}\n isOpen={isOpen}\n onClose={() => setOpen(false)}\n variant=\"navigation\"\n side=\"end\"\n portalContainer={shell}\n title={brand}\n aria-label=\"Navigation\"\n closeLabel=\"Close navigation\"\n footer={drawerActions ? <SideNavFooter>{drawerActions}</SideNavFooter> : undefined}\n >\n <SideNav\n className=\"ds-appshell__mobile-nav\"\n label={navigationLabel}\n onClick={(event) => {\n const link = event.target instanceof Element ? event.target.closest<HTMLAnchorElement>(\"a[href]\") : null;\n // Opening a link elsewhere (modifier keys, another button, a new tab) leaves this page in place.\n const opensElsewhere = event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey\n || event.altKey || link?.target === \"_blank\";\n if (link && !opensElsewhere) setOpen(false);\n }}\n >\n {navigation}\n </SideNav>\n </Drawer>\n </div>\n );\n});\n"],"mappings":"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"}
|
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
@layer components {
|
|
2
2
|
.ds-badge {
|
|
3
|
-
/* Three inks per badge: the stroke/text tone, the soft fill it sits on,
|
|
4
|
-
* and the solid pair. A tone sets all four; appearance picks which two
|
|
5
|
-
* are used. Nothing else in the component knows a colour. */
|
|
6
3
|
--badge-ink: var(--color-text-muted);
|
|
7
4
|
--badge-soft: var(--color-surface-subtle);
|
|
8
5
|
--badge-solid: var(--color-text);
|
|
9
6
|
--badge-on-solid: var(--color-surface);
|
|
7
|
+
--badge-marker: currentColor;
|
|
10
8
|
|
|
11
9
|
display: inline-flex;
|
|
12
10
|
align-items: center;
|
|
13
|
-
gap: var(--
|
|
14
|
-
padding:
|
|
11
|
+
gap: var(--badge-gap);
|
|
12
|
+
padding: var(--badge-pad-block) var(--space-2);
|
|
15
13
|
border: var(--badge-border-width) solid transparent;
|
|
16
|
-
border-radius: var(--radius
|
|
17
|
-
font-
|
|
14
|
+
border-radius: var(--badge-radius);
|
|
15
|
+
font-family: var(--font-sans);
|
|
16
|
+
font-size: var(--badge-font-size);
|
|
18
17
|
font-weight: var(--font-weight-bold);
|
|
19
|
-
line-height: var(--line-height
|
|
18
|
+
line-height: var(--badge-line-height);
|
|
19
|
+
letter-spacing: var(--badge-tracking);
|
|
20
|
+
text-transform: uppercase;
|
|
20
21
|
white-space: nowrap;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
.
|
|
24
|
-
padding: 2px 10px;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/* A count reads as one glyph: never narrower than it is tall. */
|
|
24
|
+
/* Counts keep their numeric treatment instead of label tracking and case. */
|
|
28
25
|
.ds-badge[data-shape="count"] {
|
|
29
26
|
justify-content: center;
|
|
30
|
-
min-inline-size: var(--
|
|
31
|
-
padding-inline: var(--
|
|
27
|
+
min-inline-size: var(--badge-count-min);
|
|
28
|
+
padding-inline: var(--badge-count-pad-inline);
|
|
29
|
+
font-size: var(--font-size-xs);
|
|
30
|
+
letter-spacing: normal;
|
|
31
|
+
text-transform: none;
|
|
32
32
|
font-variant-numeric: tabular-nums;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
/*
|
|
35
|
+
/* Keep the same border width and height for every appearance. */
|
|
36
36
|
.ds-badge[data-appearance="outline"] {
|
|
37
37
|
background: transparent;
|
|
38
38
|
border-color: var(--badge-ink);
|
|
@@ -40,8 +40,9 @@
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
.ds-badge[data-appearance="soft"] {
|
|
43
|
+
--badge-marker: var(--badge-soft-marker, currentColor);
|
|
43
44
|
background: var(--badge-soft);
|
|
44
|
-
border-color:
|
|
45
|
+
border-color: transparent;
|
|
45
46
|
color: var(--badge-ink);
|
|
46
47
|
}
|
|
47
48
|
|
|
@@ -52,16 +53,18 @@
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
.ds-badge__dot {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
flex: none;
|
|
57
|
+
inline-size: var(--badge-marker-size);
|
|
58
|
+
block-size: var(--badge-marker-size);
|
|
59
|
+
border-radius: 1px;
|
|
60
|
+
background: var(--badge-marker);
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
/* ── Publication tones ───────────────────────────────────────────────── */
|
|
62
64
|
.ds-badge[data-tone="draft"] {
|
|
63
65
|
--badge-ink: var(--status-draft-text);
|
|
64
66
|
--badge-soft: var(--status-draft-soft);
|
|
67
|
+
--badge-soft-marker: var(--status-draft);
|
|
65
68
|
--badge-solid: var(--color-text-muted);
|
|
66
69
|
--badge-on-solid: var(--color-surface);
|
|
67
70
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../Button/index.cjs"),t=require("../../chunks/mergeRefs-Bc3qS0Tt.cjs");let n=require("react"),r=require("react-dom"),i=require("react/jsx-runtime");function a(e,t
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../Button/index.cjs"),t=require("../../chunks/mergeRefs-Bc3qS0Tt.cjs");let n=require("react"),r=require("react-dom"),i=require("react/jsx-runtime");function a(e,t){let[r,i]=(0,n.useState)(e),[a,o]=(0,n.useState)(!1);return r!==e&&(i(e),o(!e)),(0,n.useEffect)(()=>{if(!a||e)return;let n=getComputedStyle(t.current).transitionDuration.split(`,`),r=Math.max(0,...n.map(e=>parseFloat(e)*(e.trim().endsWith(`ms`)?1:1e3)||0)),i=window.setTimeout(()=>o(!1),r);return()=>window.clearTimeout(i)},[a,e,t]),[a,o]}var o=(0,n.forwardRef)(function({isOpen:o,onClose:s,title:c,description:l,side:u=`end`,size:d=`md`,variant:f=`default`,closeLabel:p=`Close`,portalContainer:m,footer:h,className:g,children:_,...v},y){let b=(0,n.useRef)(null),x=(0,n.useRef)(null),S=(0,n.useRef)(null),C=(0,n.useRef)(s),w=(0,n.useId)(),T=(0,n.useId)(),[E,D]=a(o,x);return(0,n.useEffect)(()=>{C.current=s},[s]),(0,n.useEffect)(()=>{if(!o)return;let e=document.activeElement,t={preventScroll:!0},n=`:is(button, [href], input, select, textarea, [tabindex]):not(:disabled):not([tabindex='-1'])`;((f===`navigation`?S.current:b.current?.querySelector(n))??b.current)?.focus(t);let r=e=>{if(e.key===`Escape`){if(e.defaultPrevented)return;e.preventDefault(),C.current();return}if(e.key!==`Tab`)return;let t=Array.from(b.current?.querySelectorAll(n)??[]);if(t.length===0)return;let r=t[0],i=t[t.length-1];e.shiftKey&&(document.activeElement===r||!b.current?.contains(document.activeElement))?(e.preventDefault(),i.focus()):!e.shiftKey&&(document.activeElement===i||!b.current?.contains(document.activeElement))&&(e.preventDefault(),r.focus())};window.addEventListener(`keydown`,r);let i=document.body.style.overflow;return document.body.style.overflow=`hidden`,()=>{window.removeEventListener(`keydown`,r),document.body.style.overflow=i,e?.focus(t)}},[o,f,m]),!o&&!E||typeof document>`u`?null:(0,r.createPortal)((0,i.jsx)(`div`,{ref:e=>{x.current=e,e&&(e.inert=!o)},className:`ds-drawer-scrim`,dir:v.dir,"data-side":u,"data-variant":f,"data-contained":m?``:void 0,"data-state":o?`open`:`closed`,"aria-hidden":!o||void 0,onTransitionEnd:e=>{e.target===e.currentTarget&&e.propertyName===`opacity`&&!o&&D(!1)},onMouseDown:e=>o&&e.target===e.currentTarget&&C.current(),children:(0,i.jsxs)(`div`,{...v,ref:t.t(b,y),role:`dialog`,"aria-modal":`true`,"aria-labelledby":v[`aria-label`]?void 0:v[`aria-labelledby`]??w,"aria-describedby":l?T:void 0,tabIndex:-1,"data-side":u,"data-size":d,"data-variant":f,className:[`ds-drawer`,g].filter(Boolean).join(` `),children:[(0,i.jsxs)(`header`,{className:`ds-drawer__head`,children:[(0,i.jsxs)(`div`,{className:`ds-drawer__titles`,children:[(0,i.jsx)(`h2`,{id:w,className:`ds-drawer__title`,children:c}),l&&(0,i.jsx)(`p`,{id:T,className:`ds-drawer__description`,children:l})]}),(0,i.jsx)(e.Button,{ref:S,variant:`simple`,size:f===`navigation`?`lg`:`sm`,isIconOnly:!0,iconStart:`x`,className:f===`navigation`?`ds-drawer__close`:void 0,"aria-label":p,onClick:()=>C.current()})]}),(0,i.jsx)(`div`,{className:`ds-drawer__body`,children:_}),h&&(0,i.jsx)(`footer`,{className:`ds-drawer__footer`,children:h})]})}),m??document.body)});exports.Drawer=o;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["useState","forwardRef","useRef","useId","createPortal","mergeRefs","Button","require_components_Button_index","require_mergeRefs","react","react_dom","react_jsx_runtime","useDrawerExit","previousOpen","setPreviousOpen","isOpen","exiting","setExiting","animated","durations","scrimRef","duration","value","timeout","Drawer","rest","panelRef","closeRef","onCloseRef","onClose","titleId","descriptionId","variant","previous","focusOptions","selector","onKeyDown","event","focusable","first","last","overflow","portalContainer","node","side","ref","description","size","className","title","closeLabel","footer"],"sources":["../../../src/components/Drawer/index.tsx"],"sourcesContent":["import { forwardRef, useEffect, useId, useRef, useState, type HTMLAttributes, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { Button } from \"../Button\";\nimport { mergeRefs } from \"../../internal/mergeRefs\";\nimport \"./style.css\";\n\nexport type DrawerSide = \"end\" | \"start\" | \"bottom\";\nexport type DrawerSize = \"md\" | \"wide\";\n\nexport interface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n isOpen: boolean;\n /** Escape, the scrim and the close button all call this. */\n onClose: () => void;\n title: ReactNode;\n description?: string;\n /** Which edge the panel is anchored to. */\n side?: DrawerSide;\n size?: DrawerSize;\n /** Navigation uses a compact, square panel and animates its exit. */\n variant?: \"default\" | \"navigation\";\n /** Accessible name of the dismiss button. */\n closeLabel?: string;\n /**\n * Defaults to document.body, covering the viewport. A navigation drawer\n * portaled into a positioned element, such as an app shell, stays inside it.\n */\n portalContainer?: HTMLElement | null;\n /** Actions, right-aligned. The confirming action goes last. */\n footer?: ReactNode;\n children?: ReactNode;\n}\n\nfunction useDrawerExit(isOpen: boolean, animated: boolean, scrimRef: RefObject<HTMLDivElement | null>) {\n const [previousOpen, setPreviousOpen] = useState(isOpen);\n const [exiting, setExiting] = useState(false);\n\n if (previousOpen !== isOpen) {\n setPreviousOpen(isOpen);\n setExiting(!isOpen && animated);\n }\n\n useEffect(() => {\n if (!exiting || isOpen) return;\n // Read the actual transition, including token overrides and reduced motion.\n const durations = getComputedStyle(scrimRef.current!).transitionDuration.split(\",\");\n const duration = Math.max(0, ...durations.map((value) =>\n parseFloat(value) * (value.trim().endsWith(\"ms\") ? 1 : 1000) || 0,\n ));\n const timeout = window.setTimeout(() => setExiting(false), duration);\n return () => window.clearTimeout(timeout);\n }, [exiting, isOpen, scrimRef]);\n\n return [exiting, setExiting] as const;\n}\n\n/**\n * A side panel for work that belongs beside the page rather than on top of it\n * — editing one record, a filter set, a revision history. Same frame, rules\n * and footer band as `Modal`; focus is trapped while open.\n */\nexport const Drawer = forwardRef<HTMLDivElement, DrawerProps>(function Drawer(\n {\n isOpen,\n onClose,\n title,\n description,\n side = \"end\",\n size = \"md\",\n variant = \"default\",\n closeLabel = \"Close\",\n portalContainer,\n footer,\n className,\n children,\n ...rest\n },\n ref,\n) {\n const panelRef = useRef<HTMLDivElement | null>(null);\n const scrimRef = useRef<HTMLDivElement | null>(null);\n const closeRef = useRef<HTMLButtonElement | null>(null);\n const onCloseRef = useRef(onClose);\n const titleId = useId();\n const descriptionId = useId();\n const [exiting, setExiting] = useDrawerExit(isOpen, variant === \"navigation\", scrimRef);\n\n useEffect(() => {\n onCloseRef.current = onClose;\n }, [onClose]);\n\n useEffect(() => {\n if (!isOpen) return;\n\n const previous = document.activeElement as HTMLElement | null;\n // Navigation starts off-screen; focusing it must not scroll the shell with it.\n const focusOptions = variant === \"navigation\" ? { preventScroll: true } : undefined;\n const selector = \":is(button, [href], input, select, textarea, [tabindex]):not(:disabled):not([tabindex='-1'])\";\n const initialFocus = variant === \"navigation\" ? closeRef.current : panelRef.current?.querySelector<HTMLElement>(selector);\n (initialFocus ?? panelRef.current)?.focus(focusOptions);\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n // A popup inside the panel (Menu, Select, DateField) claims its Escape.\n if (event.defaultPrevented) return;\n event.preventDefault();\n onCloseRef.current();\n return;\n }\n if (event.key !== \"Tab\") return;\n const focusable = Array.from(\n panelRef.current?.querySelectorAll<HTMLElement>(\n selector,\n ) ?? [],\n );\n if (focusable.length === 0) return;\n const first = focusable[0]!;\n const last = focusable[focusable.length - 1]!;\n if (event.shiftKey && (document.activeElement === first || !panelRef.current?.contains(document.activeElement))) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && (document.activeElement === last || !panelRef.current?.contains(document.activeElement))) {\n event.preventDefault();\n first.focus();\n }\n };\n\n // On window, so document-level popup handlers inside the panel run first.\n window.addEventListener(\"keydown\", onKeyDown);\n const overflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n\n return () => {\n window.removeEventListener(\"keydown\", onKeyDown);\n document.body.style.overflow = overflow;\n previous?.focus(focusOptions);\n };\n }, [isOpen, variant, portalContainer]);\n\n if ((!isOpen && !exiting) || typeof document === \"undefined\") return null;\n\n return createPortal(\n <div\n ref={(node) => {\n scrimRef.current = node;\n if (node) node.inert = !isOpen;\n }}\n className=\"ds-drawer-scrim\"\n data-side={side}\n data-variant={variant}\n data-contained={portalContainer ? \"\" : undefined}\n data-state={isOpen ? \"open\" : \"closed\"}\n aria-hidden={!isOpen || undefined}\n onTransitionEnd={(event) => {\n if (event.target === event.currentTarget && event.propertyName === \"opacity\" && !isOpen) setExiting(false);\n }}\n onMouseDown={(event) => isOpen && event.target === event.currentTarget && onCloseRef.current()}\n >\n <div\n {...rest}\n ref={mergeRefs(panelRef, ref)}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={rest[\"aria-label\"] ? undefined : (rest[\"aria-labelledby\"] ?? titleId)}\n aria-describedby={description ? descriptionId : undefined}\n tabIndex={-1}\n data-side={side}\n data-size={size}\n data-variant={variant}\n className={[\"ds-drawer\", className].filter(Boolean).join(\" \")}\n >\n <header className=\"ds-drawer__head\">\n <div className=\"ds-drawer__titles\">\n <h2 id={titleId} className=\"ds-drawer__title\">\n {title}\n </h2>\n {description && (\n <p id={descriptionId} className=\"ds-drawer__description\">\n {description}\n </p>\n )}\n </div>\n <Button\n ref={closeRef}\n variant=\"simple\"\n size={variant === \"navigation\" ? \"lg\" : \"sm\"}\n isIconOnly\n iconStart=\"x\"\n className={variant === \"navigation\" ? \"ds-drawer__close\" : undefined}\n aria-label={closeLabel}\n onClick={() => onCloseRef.current()}\n />\n </header>\n <div className=\"ds-drawer__body\">{children}</div>\n {footer && <footer className=\"ds-drawer__footer\">{footer}</footer>}\n </div>\n </div>,\n portalContainer ?? document.body,\n );\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["useState","forwardRef","useRef","useId","createPortal","mergeRefs","Button","require_components_Button_index","require_mergeRefs","react","react_dom","react_jsx_runtime","useDrawerExit","previousOpen","setPreviousOpen","isOpen","exiting","setExiting","durations","scrimRef","duration","value","timeout","Drawer","rest","panelRef","closeRef","onCloseRef","onClose","titleId","descriptionId","previous","focusOptions","selector","variant","onKeyDown","event","focusable","first","last","overflow","portalContainer","node","side","ref","description","size","className","title","closeLabel","footer"],"sources":["../../../src/components/Drawer/index.tsx"],"sourcesContent":["import { forwardRef, useEffect, useId, useRef, useState, type HTMLAttributes, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { Button } from \"../Button\";\nimport { mergeRefs } from \"../../internal/mergeRefs\";\nimport \"./style.css\";\n\nexport type DrawerSide = \"end\" | \"start\" | \"bottom\";\nexport type DrawerSize = \"md\" | \"wide\";\n\nexport interface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n isOpen: boolean;\n /** Escape, the scrim and the close button all call this. */\n onClose: () => void;\n title: ReactNode;\n description?: string;\n /** Which edge the panel is anchored to. */\n side?: DrawerSide;\n size?: DrawerSize;\n /** Navigation uses a compact panel, header and footer. Both variants slide in and out. */\n variant?: \"default\" | \"navigation\";\n /** Accessible name of the dismiss button. */\n closeLabel?: string;\n /**\n * Defaults to document.body, covering the viewport. A navigation drawer\n * portaled into a positioned element, such as an app shell, stays inside it.\n */\n portalContainer?: HTMLElement | null;\n /** Actions, right-aligned. The confirming action goes last. */\n footer?: ReactNode;\n children?: ReactNode;\n}\n\nfunction useDrawerExit(isOpen: boolean, scrimRef: RefObject<HTMLDivElement | null>) {\n const [previousOpen, setPreviousOpen] = useState(isOpen);\n const [exiting, setExiting] = useState(false);\n\n if (previousOpen !== isOpen) {\n setPreviousOpen(isOpen);\n setExiting(!isOpen);\n }\n\n useEffect(() => {\n if (!exiting || isOpen) return;\n // Read the actual transition, including token overrides and reduced motion.\n const durations = getComputedStyle(scrimRef.current!).transitionDuration.split(\",\");\n const duration = Math.max(0, ...durations.map((value) =>\n parseFloat(value) * (value.trim().endsWith(\"ms\") ? 1 : 1000) || 0,\n ));\n const timeout = window.setTimeout(() => setExiting(false), duration);\n return () => window.clearTimeout(timeout);\n }, [exiting, isOpen, scrimRef]);\n\n return [exiting, setExiting] as const;\n}\n\n/**\n * A side panel for work that belongs beside the page rather than on top of it\n * — editing one record, a filter set, a revision history. Same frame, rules\n * and footer band as `Modal`, with square corners and a full slide through\n * its anchored edge. Focus is trapped while open.\n */\nexport const Drawer = forwardRef<HTMLDivElement, DrawerProps>(function Drawer(\n {\n isOpen,\n onClose,\n title,\n description,\n side = \"end\",\n size = \"md\",\n variant = \"default\",\n closeLabel = \"Close\",\n portalContainer,\n footer,\n className,\n children,\n ...rest\n },\n ref,\n) {\n const panelRef = useRef<HTMLDivElement | null>(null);\n const scrimRef = useRef<HTMLDivElement | null>(null);\n const closeRef = useRef<HTMLButtonElement | null>(null);\n const onCloseRef = useRef(onClose);\n const titleId = useId();\n const descriptionId = useId();\n const [exiting, setExiting] = useDrawerExit(isOpen, scrimRef);\n\n useEffect(() => {\n onCloseRef.current = onClose;\n }, [onClose]);\n\n useEffect(() => {\n if (!isOpen) return;\n\n const previous = document.activeElement as HTMLElement | null;\n // Panels start off-screen; focusing them must not scroll the page with them.\n const focusOptions = { preventScroll: true };\n const selector = \":is(button, [href], input, select, textarea, [tabindex]):not(:disabled):not([tabindex='-1'])\";\n const initialFocus = variant === \"navigation\" ? closeRef.current : panelRef.current?.querySelector<HTMLElement>(selector);\n (initialFocus ?? panelRef.current)?.focus(focusOptions);\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n // A popup inside the panel (Menu, Select, DateField) claims its Escape.\n if (event.defaultPrevented) return;\n event.preventDefault();\n onCloseRef.current();\n return;\n }\n if (event.key !== \"Tab\") return;\n const focusable = Array.from(\n panelRef.current?.querySelectorAll<HTMLElement>(\n selector,\n ) ?? [],\n );\n if (focusable.length === 0) return;\n const first = focusable[0]!;\n const last = focusable[focusable.length - 1]!;\n if (event.shiftKey && (document.activeElement === first || !panelRef.current?.contains(document.activeElement))) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && (document.activeElement === last || !panelRef.current?.contains(document.activeElement))) {\n event.preventDefault();\n first.focus();\n }\n };\n\n // On window, so document-level popup handlers inside the panel run first.\n window.addEventListener(\"keydown\", onKeyDown);\n const overflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n\n return () => {\n window.removeEventListener(\"keydown\", onKeyDown);\n document.body.style.overflow = overflow;\n previous?.focus(focusOptions);\n };\n }, [isOpen, variant, portalContainer]);\n\n if ((!isOpen && !exiting) || typeof document === \"undefined\") return null;\n\n return createPortal(\n <div\n ref={(node) => {\n scrimRef.current = node;\n if (node) node.inert = !isOpen;\n }}\n className=\"ds-drawer-scrim\"\n dir={rest.dir}\n data-side={side}\n data-variant={variant}\n data-contained={portalContainer ? \"\" : undefined}\n data-state={isOpen ? \"open\" : \"closed\"}\n aria-hidden={!isOpen || undefined}\n onTransitionEnd={(event) => {\n if (event.target === event.currentTarget && event.propertyName === \"opacity\" && !isOpen) setExiting(false);\n }}\n onMouseDown={(event) => isOpen && event.target === event.currentTarget && onCloseRef.current()}\n >\n <div\n {...rest}\n ref={mergeRefs(panelRef, ref)}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={rest[\"aria-label\"] ? undefined : (rest[\"aria-labelledby\"] ?? titleId)}\n aria-describedby={description ? descriptionId : undefined}\n tabIndex={-1}\n data-side={side}\n data-size={size}\n data-variant={variant}\n className={[\"ds-drawer\", className].filter(Boolean).join(\" \")}\n >\n <header className=\"ds-drawer__head\">\n <div className=\"ds-drawer__titles\">\n <h2 id={titleId} className=\"ds-drawer__title\">\n {title}\n </h2>\n {description && (\n <p id={descriptionId} className=\"ds-drawer__description\">\n {description}\n </p>\n )}\n </div>\n <Button\n ref={closeRef}\n variant=\"simple\"\n size={variant === \"navigation\" ? \"lg\" : \"sm\"}\n isIconOnly\n iconStart=\"x\"\n className={variant === \"navigation\" ? \"ds-drawer__close\" : undefined}\n aria-label={closeLabel}\n onClick={() => onCloseRef.current()}\n />\n </header>\n <div className=\"ds-drawer__body\">{children}</div>\n {footer && <footer className=\"ds-drawer__footer\">{footer}</footer>}\n </div>\n </div>,\n portalContainer ?? document.body,\n );\n});\n"],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ export interface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, "title
|
|
|
10
10
|
/** Which edge the panel is anchored to. */
|
|
11
11
|
side?: DrawerSide;
|
|
12
12
|
size?: DrawerSize;
|
|
13
|
-
/** Navigation uses a compact,
|
|
13
|
+
/** Navigation uses a compact panel, header and footer. Both variants slide in and out. */
|
|
14
14
|
variant?: "default" | "navigation";
|
|
15
15
|
/** Accessible name of the dismiss button. */
|
|
16
16
|
closeLabel?: string;
|
|
@@ -26,7 +26,8 @@ export interface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, "title
|
|
|
26
26
|
/**
|
|
27
27
|
* A side panel for work that belongs beside the page rather than on top of it
|
|
28
28
|
* — editing one record, a filter set, a revision history. Same frame, rules
|
|
29
|
-
* and footer band as `Modal
|
|
29
|
+
* and footer band as `Modal`, with square corners and a full slide through
|
|
30
|
+
* its anchored edge. Focus is trapped while open.
|
|
30
31
|
*/
|
|
31
32
|
export declare const Drawer: import("react").ForwardRefExoticComponent<DrawerProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
32
33
|
//# sourceMappingURL=index.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../src/components/Drawer/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,cAAc,EAAE,KAAK,SAAS,EAAkB,MAAM,OAAO,CAAC;AAI5H,OAAO,aAAa,CAAC;AAErB,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AACpD,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,MAAM,CAAC;AAEvC,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAChF,MAAM,EAAE,OAAO,CAAC;IAChB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,
|
|
1
|
+
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../src/components/Drawer/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,cAAc,EAAE,KAAK,SAAS,EAAkB,MAAM,OAAO,CAAC;AAI5H,OAAO,aAAa,CAAC;AAErB,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AACpD,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,MAAM,CAAC;AAEvC,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAChF,MAAM,EAAE,OAAO,CAAC;IAChB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,0FAA0F;IAC1F,OAAO,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;IACnC,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,eAAe,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACrC,+DAA+D;IAC/D,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAyBD;;;;;GAKG;AACH,eAAO,MAAM,MAAM,wGA2IjB,CAAC"}
|
|
@@ -10,7 +10,7 @@ export interface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, "title
|
|
|
10
10
|
/** Which edge the panel is anchored to. */
|
|
11
11
|
side?: DrawerSide;
|
|
12
12
|
size?: DrawerSize;
|
|
13
|
-
/** Navigation uses a compact,
|
|
13
|
+
/** Navigation uses a compact panel, header and footer. Both variants slide in and out. */
|
|
14
14
|
variant?: "default" | "navigation";
|
|
15
15
|
/** Accessible name of the dismiss button. */
|
|
16
16
|
closeLabel?: string;
|
|
@@ -26,7 +26,8 @@ export interface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, "title
|
|
|
26
26
|
/**
|
|
27
27
|
* A side panel for work that belongs beside the page rather than on top of it
|
|
28
28
|
* — editing one record, a filter set, a revision history. Same frame, rules
|
|
29
|
-
* and footer band as `Modal
|
|
29
|
+
* and footer band as `Modal`, with square corners and a full slide through
|
|
30
|
+
* its anchored edge. Focus is trapped while open.
|
|
30
31
|
*/
|
|
31
32
|
export declare const Drawer: import("react").ForwardRefExoticComponent<DrawerProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
32
33
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Drawer/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,cAAc,EAAE,KAAK,SAAS,EAAkB,MAAM,OAAO,CAAC;AAI5H,OAAO,aAAa,CAAC;AAErB,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AACpD,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,MAAM,CAAC;AAEvC,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAChF,MAAM,EAAE,OAAO,CAAC;IAChB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Drawer/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,cAAc,EAAE,KAAK,SAAS,EAAkB,MAAM,OAAO,CAAC;AAI5H,OAAO,aAAa,CAAC;AAErB,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AACpD,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,MAAM,CAAC;AAEvC,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAChF,MAAM,EAAE,OAAO,CAAC;IAChB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,0FAA0F;IAC1F,OAAO,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;IACnC,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,eAAe,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACrC,+DAA+D;IAC/D,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAyBD;;;;;GAKG;AACH,eAAO,MAAM,MAAM,wGA2IjB,CAAC"}
|
|
@@ -4,25 +4,25 @@ import { forwardRef as n, useEffect as r, useId as i, useRef as a, useState as o
|
|
|
4
4
|
import { createPortal as s } from "react-dom";
|
|
5
5
|
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
6
6
|
//#region src/components/Drawer/index.tsx
|
|
7
|
-
function u(e, t
|
|
8
|
-
let [
|
|
9
|
-
return
|
|
10
|
-
if (!
|
|
11
|
-
let
|
|
7
|
+
function u(e, t) {
|
|
8
|
+
let [n, i] = o(e), [a, s] = o(!1);
|
|
9
|
+
return n !== e && (i(e), s(!e)), r(() => {
|
|
10
|
+
if (!a || e) return;
|
|
11
|
+
let n = getComputedStyle(t.current).transitionDuration.split(","), r = Math.max(0, ...n.map((e) => parseFloat(e) * (e.trim().endsWith("ms") ? 1 : 1e3) || 0)), i = window.setTimeout(() => s(!1), r);
|
|
12
12
|
return () => window.clearTimeout(i);
|
|
13
13
|
}, [
|
|
14
|
-
|
|
14
|
+
a,
|
|
15
15
|
e,
|
|
16
|
-
|
|
17
|
-
]), [
|
|
16
|
+
t
|
|
17
|
+
]), [a, s];
|
|
18
18
|
}
|
|
19
19
|
var d = n(function({ isOpen: n, onClose: o, title: d, description: f, side: p = "end", size: m = "md", variant: h = "default", closeLabel: g = "Close", portalContainer: _, footer: v, className: y, children: b, ...x }, S) {
|
|
20
|
-
let C = a(null), w = a(null), T = a(null), E = a(o), D = i(), O = i(), [k, A] = u(n,
|
|
20
|
+
let C = a(null), w = a(null), T = a(null), E = a(o), D = i(), O = i(), [k, A] = u(n, w);
|
|
21
21
|
return r(() => {
|
|
22
22
|
E.current = o;
|
|
23
23
|
}, [o]), r(() => {
|
|
24
24
|
if (!n) return;
|
|
25
|
-
let e = document.activeElement, t =
|
|
25
|
+
let e = document.activeElement, t = { preventScroll: !0 }, r = ":is(button, [href], input, select, textarea, [tabindex]):not(:disabled):not([tabindex='-1'])";
|
|
26
26
|
((h === "navigation" ? T.current : C.current?.querySelector(r)) ?? C.current)?.focus(t);
|
|
27
27
|
let i = (e) => {
|
|
28
28
|
if (e.key === "Escape") {
|
|
@@ -50,6 +50,7 @@ var d = n(function({ isOpen: n, onClose: o, title: d, description: f, side: p =
|
|
|
50
50
|
w.current = e, e && (e.inert = !n);
|
|
51
51
|
},
|
|
52
52
|
className: "ds-drawer-scrim",
|
|
53
|
+
dir: x.dir,
|
|
53
54
|
"data-side": p,
|
|
54
55
|
"data-variant": h,
|
|
55
56
|
"data-contained": _ ? "" : void 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["useDrawerExit","previousOpen","setPreviousOpen","useState","isOpen","exiting","setExiting","animated","useEffect","durations","scrimRef","duration","value","timeout","Drawer","forwardRef","rest","panelRef","useRef","closeRef","onCloseRef","onClose","titleId","useId","descriptionId","variant","previous","focusOptions","selector","onKeyDown","event","focusable","first","last","overflow","portalContainer","createPortal","node","side","mergeRefs","ref","description","size","className","title","Button","closeLabel","footer"],"sources":["../../../src/components/Drawer/index.tsx"],"sourcesContent":["import { forwardRef, useEffect, useId, useRef, useState, type HTMLAttributes, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { Button } from \"../Button\";\nimport { mergeRefs } from \"../../internal/mergeRefs\";\nimport \"./style.css\";\n\nexport type DrawerSide = \"end\" | \"start\" | \"bottom\";\nexport type DrawerSize = \"md\" | \"wide\";\n\nexport interface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n isOpen: boolean;\n /** Escape, the scrim and the close button all call this. */\n onClose: () => void;\n title: ReactNode;\n description?: string;\n /** Which edge the panel is anchored to. */\n side?: DrawerSide;\n size?: DrawerSize;\n /** Navigation uses a compact, square panel and animates its exit. */\n variant?: \"default\" | \"navigation\";\n /** Accessible name of the dismiss button. */\n closeLabel?: string;\n /**\n * Defaults to document.body, covering the viewport. A navigation drawer\n * portaled into a positioned element, such as an app shell, stays inside it.\n */\n portalContainer?: HTMLElement | null;\n /** Actions, right-aligned. The confirming action goes last. */\n footer?: ReactNode;\n children?: ReactNode;\n}\n\nfunction useDrawerExit(isOpen: boolean, animated: boolean, scrimRef: RefObject<HTMLDivElement | null>) {\n const [previousOpen, setPreviousOpen] = useState(isOpen);\n const [exiting, setExiting] = useState(false);\n\n if (previousOpen !== isOpen) {\n setPreviousOpen(isOpen);\n setExiting(!isOpen && animated);\n }\n\n useEffect(() => {\n if (!exiting || isOpen) return;\n // Read the actual transition, including token overrides and reduced motion.\n const durations = getComputedStyle(scrimRef.current!).transitionDuration.split(\",\");\n const duration = Math.max(0, ...durations.map((value) =>\n parseFloat(value) * (value.trim().endsWith(\"ms\") ? 1 : 1000) || 0,\n ));\n const timeout = window.setTimeout(() => setExiting(false), duration);\n return () => window.clearTimeout(timeout);\n }, [exiting, isOpen, scrimRef]);\n\n return [exiting, setExiting] as const;\n}\n\n/**\n * A side panel for work that belongs beside the page rather than on top of it\n * — editing one record, a filter set, a revision history. Same frame, rules\n * and footer band as `Modal`; focus is trapped while open.\n */\nexport const Drawer = forwardRef<HTMLDivElement, DrawerProps>(function Drawer(\n {\n isOpen,\n onClose,\n title,\n description,\n side = \"end\",\n size = \"md\",\n variant = \"default\",\n closeLabel = \"Close\",\n portalContainer,\n footer,\n className,\n children,\n ...rest\n },\n ref,\n) {\n const panelRef = useRef<HTMLDivElement | null>(null);\n const scrimRef = useRef<HTMLDivElement | null>(null);\n const closeRef = useRef<HTMLButtonElement | null>(null);\n const onCloseRef = useRef(onClose);\n const titleId = useId();\n const descriptionId = useId();\n const [exiting, setExiting] = useDrawerExit(isOpen, variant === \"navigation\", scrimRef);\n\n useEffect(() => {\n onCloseRef.current = onClose;\n }, [onClose]);\n\n useEffect(() => {\n if (!isOpen) return;\n\n const previous = document.activeElement as HTMLElement | null;\n // Navigation starts off-screen; focusing it must not scroll the shell with it.\n const focusOptions = variant === \"navigation\" ? { preventScroll: true } : undefined;\n const selector = \":is(button, [href], input, select, textarea, [tabindex]):not(:disabled):not([tabindex='-1'])\";\n const initialFocus = variant === \"navigation\" ? closeRef.current : panelRef.current?.querySelector<HTMLElement>(selector);\n (initialFocus ?? panelRef.current)?.focus(focusOptions);\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n // A popup inside the panel (Menu, Select, DateField) claims its Escape.\n if (event.defaultPrevented) return;\n event.preventDefault();\n onCloseRef.current();\n return;\n }\n if (event.key !== \"Tab\") return;\n const focusable = Array.from(\n panelRef.current?.querySelectorAll<HTMLElement>(\n selector,\n ) ?? [],\n );\n if (focusable.length === 0) return;\n const first = focusable[0]!;\n const last = focusable[focusable.length - 1]!;\n if (event.shiftKey && (document.activeElement === first || !panelRef.current?.contains(document.activeElement))) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && (document.activeElement === last || !panelRef.current?.contains(document.activeElement))) {\n event.preventDefault();\n first.focus();\n }\n };\n\n // On window, so document-level popup handlers inside the panel run first.\n window.addEventListener(\"keydown\", onKeyDown);\n const overflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n\n return () => {\n window.removeEventListener(\"keydown\", onKeyDown);\n document.body.style.overflow = overflow;\n previous?.focus(focusOptions);\n };\n }, [isOpen, variant, portalContainer]);\n\n if ((!isOpen && !exiting) || typeof document === \"undefined\") return null;\n\n return createPortal(\n <div\n ref={(node) => {\n scrimRef.current = node;\n if (node) node.inert = !isOpen;\n }}\n className=\"ds-drawer-scrim\"\n data-side={side}\n data-variant={variant}\n data-contained={portalContainer ? \"\" : undefined}\n data-state={isOpen ? \"open\" : \"closed\"}\n aria-hidden={!isOpen || undefined}\n onTransitionEnd={(event) => {\n if (event.target === event.currentTarget && event.propertyName === \"opacity\" && !isOpen) setExiting(false);\n }}\n onMouseDown={(event) => isOpen && event.target === event.currentTarget && onCloseRef.current()}\n >\n <div\n {...rest}\n ref={mergeRefs(panelRef, ref)}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={rest[\"aria-label\"] ? undefined : (rest[\"aria-labelledby\"] ?? titleId)}\n aria-describedby={description ? descriptionId : undefined}\n tabIndex={-1}\n data-side={side}\n data-size={size}\n data-variant={variant}\n className={[\"ds-drawer\", className].filter(Boolean).join(\" \")}\n >\n <header className=\"ds-drawer__head\">\n <div className=\"ds-drawer__titles\">\n <h2 id={titleId} className=\"ds-drawer__title\">\n {title}\n </h2>\n {description && (\n <p id={descriptionId} className=\"ds-drawer__description\">\n {description}\n </p>\n )}\n </div>\n <Button\n ref={closeRef}\n variant=\"simple\"\n size={variant === \"navigation\" ? \"lg\" : \"sm\"}\n isIconOnly\n iconStart=\"x\"\n className={variant === \"navigation\" ? \"ds-drawer__close\" : undefined}\n aria-label={closeLabel}\n onClick={() => onCloseRef.current()}\n />\n </header>\n <div className=\"ds-drawer__body\">{children}</div>\n {footer && <footer className=\"ds-drawer__footer\">{footer}</footer>}\n </div>\n </div>,\n portalContainer ?? document.body,\n );\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["useDrawerExit","previousOpen","setPreviousOpen","useState","isOpen","exiting","setExiting","useEffect","durations","scrimRef","duration","value","timeout","Drawer","forwardRef","rest","panelRef","useRef","closeRef","onCloseRef","onClose","titleId","useId","descriptionId","previous","focusOptions","selector","variant","onKeyDown","event","focusable","first","last","overflow","portalContainer","createPortal","node","side","mergeRefs","ref","description","size","className","title","Button","closeLabel","footer"],"sources":["../../../src/components/Drawer/index.tsx"],"sourcesContent":["import { forwardRef, useEffect, useId, useRef, useState, type HTMLAttributes, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { Button } from \"../Button\";\nimport { mergeRefs } from \"../../internal/mergeRefs\";\nimport \"./style.css\";\n\nexport type DrawerSide = \"end\" | \"start\" | \"bottom\";\nexport type DrawerSize = \"md\" | \"wide\";\n\nexport interface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n isOpen: boolean;\n /** Escape, the scrim and the close button all call this. */\n onClose: () => void;\n title: ReactNode;\n description?: string;\n /** Which edge the panel is anchored to. */\n side?: DrawerSide;\n size?: DrawerSize;\n /** Navigation uses a compact panel, header and footer. Both variants slide in and out. */\n variant?: \"default\" | \"navigation\";\n /** Accessible name of the dismiss button. */\n closeLabel?: string;\n /**\n * Defaults to document.body, covering the viewport. A navigation drawer\n * portaled into a positioned element, such as an app shell, stays inside it.\n */\n portalContainer?: HTMLElement | null;\n /** Actions, right-aligned. The confirming action goes last. */\n footer?: ReactNode;\n children?: ReactNode;\n}\n\nfunction useDrawerExit(isOpen: boolean, scrimRef: RefObject<HTMLDivElement | null>) {\n const [previousOpen, setPreviousOpen] = useState(isOpen);\n const [exiting, setExiting] = useState(false);\n\n if (previousOpen !== isOpen) {\n setPreviousOpen(isOpen);\n setExiting(!isOpen);\n }\n\n useEffect(() => {\n if (!exiting || isOpen) return;\n // Read the actual transition, including token overrides and reduced motion.\n const durations = getComputedStyle(scrimRef.current!).transitionDuration.split(\",\");\n const duration = Math.max(0, ...durations.map((value) =>\n parseFloat(value) * (value.trim().endsWith(\"ms\") ? 1 : 1000) || 0,\n ));\n const timeout = window.setTimeout(() => setExiting(false), duration);\n return () => window.clearTimeout(timeout);\n }, [exiting, isOpen, scrimRef]);\n\n return [exiting, setExiting] as const;\n}\n\n/**\n * A side panel for work that belongs beside the page rather than on top of it\n * — editing one record, a filter set, a revision history. Same frame, rules\n * and footer band as `Modal`, with square corners and a full slide through\n * its anchored edge. Focus is trapped while open.\n */\nexport const Drawer = forwardRef<HTMLDivElement, DrawerProps>(function Drawer(\n {\n isOpen,\n onClose,\n title,\n description,\n side = \"end\",\n size = \"md\",\n variant = \"default\",\n closeLabel = \"Close\",\n portalContainer,\n footer,\n className,\n children,\n ...rest\n },\n ref,\n) {\n const panelRef = useRef<HTMLDivElement | null>(null);\n const scrimRef = useRef<HTMLDivElement | null>(null);\n const closeRef = useRef<HTMLButtonElement | null>(null);\n const onCloseRef = useRef(onClose);\n const titleId = useId();\n const descriptionId = useId();\n const [exiting, setExiting] = useDrawerExit(isOpen, scrimRef);\n\n useEffect(() => {\n onCloseRef.current = onClose;\n }, [onClose]);\n\n useEffect(() => {\n if (!isOpen) return;\n\n const previous = document.activeElement as HTMLElement | null;\n // Panels start off-screen; focusing them must not scroll the page with them.\n const focusOptions = { preventScroll: true };\n const selector = \":is(button, [href], input, select, textarea, [tabindex]):not(:disabled):not([tabindex='-1'])\";\n const initialFocus = variant === \"navigation\" ? closeRef.current : panelRef.current?.querySelector<HTMLElement>(selector);\n (initialFocus ?? panelRef.current)?.focus(focusOptions);\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n // A popup inside the panel (Menu, Select, DateField) claims its Escape.\n if (event.defaultPrevented) return;\n event.preventDefault();\n onCloseRef.current();\n return;\n }\n if (event.key !== \"Tab\") return;\n const focusable = Array.from(\n panelRef.current?.querySelectorAll<HTMLElement>(\n selector,\n ) ?? [],\n );\n if (focusable.length === 0) return;\n const first = focusable[0]!;\n const last = focusable[focusable.length - 1]!;\n if (event.shiftKey && (document.activeElement === first || !panelRef.current?.contains(document.activeElement))) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && (document.activeElement === last || !panelRef.current?.contains(document.activeElement))) {\n event.preventDefault();\n first.focus();\n }\n };\n\n // On window, so document-level popup handlers inside the panel run first.\n window.addEventListener(\"keydown\", onKeyDown);\n const overflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n\n return () => {\n window.removeEventListener(\"keydown\", onKeyDown);\n document.body.style.overflow = overflow;\n previous?.focus(focusOptions);\n };\n }, [isOpen, variant, portalContainer]);\n\n if ((!isOpen && !exiting) || typeof document === \"undefined\") return null;\n\n return createPortal(\n <div\n ref={(node) => {\n scrimRef.current = node;\n if (node) node.inert = !isOpen;\n }}\n className=\"ds-drawer-scrim\"\n dir={rest.dir}\n data-side={side}\n data-variant={variant}\n data-contained={portalContainer ? \"\" : undefined}\n data-state={isOpen ? \"open\" : \"closed\"}\n aria-hidden={!isOpen || undefined}\n onTransitionEnd={(event) => {\n if (event.target === event.currentTarget && event.propertyName === \"opacity\" && !isOpen) setExiting(false);\n }}\n onMouseDown={(event) => isOpen && event.target === event.currentTarget && onCloseRef.current()}\n >\n <div\n {...rest}\n ref={mergeRefs(panelRef, ref)}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={rest[\"aria-label\"] ? undefined : (rest[\"aria-labelledby\"] ?? titleId)}\n aria-describedby={description ? descriptionId : undefined}\n tabIndex={-1}\n data-side={side}\n data-size={size}\n data-variant={variant}\n className={[\"ds-drawer\", className].filter(Boolean).join(\" \")}\n >\n <header className=\"ds-drawer__head\">\n <div className=\"ds-drawer__titles\">\n <h2 id={titleId} className=\"ds-drawer__title\">\n {title}\n </h2>\n {description && (\n <p id={descriptionId} className=\"ds-drawer__description\">\n {description}\n </p>\n )}\n </div>\n <Button\n ref={closeRef}\n variant=\"simple\"\n size={variant === \"navigation\" ? \"lg\" : \"sm\"}\n isIconOnly\n iconStart=\"x\"\n className={variant === \"navigation\" ? \"ds-drawer__close\" : undefined}\n aria-label={closeLabel}\n onClick={() => onCloseRef.current()}\n />\n </header>\n <div className=\"ds-drawer__body\">{children}</div>\n {footer && <footer className=\"ds-drawer__footer\">{footer}</footer>}\n </div>\n </div>,\n portalContainer ?? document.body,\n );\n});\n"],"mappings":"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"}
|