@hjmds/react 1.10.0 → 1.12.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/README.md +14 -0
- package/THIRD_PARTY_NOTICES.md +78 -0
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +1 -1
- package/dist/actions.js.map +1 -1
- package/dist/activity-heatmap.d.ts +10 -0
- package/dist/activity-heatmap.d.ts.map +1 -0
- package/dist/activity-heatmap.js +6 -0
- package/dist/activity-heatmap.js.map +1 -0
- package/dist/advanced-display.d.ts +3 -0
- package/dist/advanced-display.d.ts.map +1 -1
- package/dist/advanced-display.js +9 -7
- package/dist/advanced-display.js.map +1 -1
- package/dist/advanced-forms.js +1 -1
- package/dist/advanced-forms.js.map +1 -1
- package/dist/auth-screen.d.ts +8 -0
- package/dist/auth-screen.d.ts.map +1 -1
- package/dist/auth-screen.js +5 -2
- package/dist/auth-screen.js.map +1 -1
- package/dist/avatar-blobatar-motion.d.ts +6 -0
- package/dist/avatar-blobatar-motion.d.ts.map +1 -0
- package/dist/avatar-blobatar-motion.js +22 -0
- package/dist/avatar-blobatar-motion.js.map +1 -0
- package/dist/avatar-blobatar.d.ts +6 -0
- package/dist/avatar-blobatar.d.ts.map +1 -0
- package/dist/avatar-blobatar.js +10 -0
- package/dist/avatar-blobatar.js.map +1 -0
- package/dist/bottom-navigation.d.ts.map +1 -1
- package/dist/bottom-navigation.js +3 -3
- package/dist/bottom-navigation.js.map +1 -1
- package/dist/carousel-motion.d.ts +4 -1
- package/dist/carousel-motion.d.ts.map +1 -1
- package/dist/carousel-motion.js +12 -3
- package/dist/carousel-motion.js.map +1 -1
- package/dist/code-block.d.ts +8 -0
- package/dist/code-block.d.ts.map +1 -0
- package/dist/code-block.js +6 -0
- package/dist/code-block.js.map +1 -0
- package/dist/content-transition.d.ts +5 -2
- package/dist/content-transition.d.ts.map +1 -1
- package/dist/content-transition.js +6 -4
- package/dist/content-transition.js.map +1 -1
- package/dist/context-menu.d.ts.map +1 -1
- package/dist/context-menu.js +10 -11
- package/dist/context-menu.js.map +1 -1
- package/dist/data-table.d.ts.map +1 -1
- package/dist/data-table.js +2 -1
- package/dist/data-table.js.map +1 -1
- package/dist/duration-field.d.ts +11 -0
- package/dist/duration-field.d.ts.map +1 -0
- package/dist/duration-field.js +9 -0
- package/dist/duration-field.js.map +1 -0
- package/dist/effect-surface.d.ts +10 -0
- package/dist/effect-surface.d.ts.map +1 -0
- package/dist/effect-surface.js +57 -0
- package/dist/effect-surface.js.map +1 -0
- package/dist/evidence.d.ts +1 -1
- package/dist/evidence.js +1 -1
- package/dist/evidence.js.map +1 -1
- package/dist/feedback.js +1 -1
- package/dist/feedback.js.map +1 -1
- package/dist/folder-preview.d.ts +12 -0
- package/dist/folder-preview.d.ts.map +1 -0
- package/dist/folder-preview.js +7 -0
- package/dist/folder-preview.js.map +1 -0
- package/dist/forms.d.ts +3 -1
- package/dist/forms.d.ts.map +1 -1
- package/dist/forms.js +5 -3
- package/dist/forms.js.map +1 -1
- package/dist/gravity-letters.d.ts +8 -0
- package/dist/gravity-letters.d.ts.map +1 -0
- package/dist/gravity-letters.js +24 -0
- package/dist/gravity-letters.js.map +1 -0
- package/dist/grid-reveal.d.ts +9 -0
- package/dist/grid-reveal.d.ts.map +1 -0
- package/dist/grid-reveal.js +21 -0
- package/dist/grid-reveal.js.map +1 -0
- package/dist/icon-lucide.d.ts +11 -0
- package/dist/icon-lucide.d.ts.map +1 -0
- package/dist/icon-lucide.js +11 -0
- package/dist/icon-lucide.js.map +1 -0
- package/dist/inline-confirm.d.ts +14 -0
- package/dist/inline-confirm.d.ts.map +1 -0
- package/dist/inline-confirm.js +37 -0
- package/dist/inline-confirm.js.map +1 -0
- package/dist/menu-morph.d.ts.map +1 -1
- package/dist/menu-morph.js +9 -6
- package/dist/menu-morph.js.map +1 -1
- package/dist/menu-typeahead.d.ts +13 -0
- package/dist/menu-typeahead.d.ts.map +1 -0
- package/dist/menu-typeahead.js +17 -0
- package/dist/menu-typeahead.js.map +1 -0
- package/dist/navigation-bar.d.ts +10 -0
- package/dist/navigation-bar.d.ts.map +1 -0
- package/dist/navigation-bar.js +10 -0
- package/dist/navigation-bar.js.map +1 -0
- package/dist/navigation.d.ts +3 -3
- package/dist/navigation.d.ts.map +1 -1
- package/dist/navigation.js +63 -22
- package/dist/navigation.js.map +1 -1
- package/dist/notification-bell.d.ts +11 -0
- package/dist/notification-bell.d.ts.map +1 -0
- package/dist/notification-bell.js +27 -0
- package/dist/notification-bell.js.map +1 -0
- package/dist/overlays.d.ts +0 -2
- package/dist/overlays.d.ts.map +1 -1
- package/dist/overlays.js +5 -18
- package/dist/overlays.js.map +1 -1
- package/dist/provider-button.d.ts.map +1 -1
- package/dist/provider-button.js +2 -2
- package/dist/provider-button.js.map +1 -1
- package/dist/reaction-picker.d.ts +11 -0
- package/dist/reaction-picker.d.ts.map +1 -0
- package/dist/reaction-picker.js +9 -0
- package/dist/reaction-picker.js.map +1 -0
- package/dist/scroll-progress.d.ts +10 -0
- package/dist/scroll-progress.d.ts.map +1 -0
- package/dist/scroll-progress.js +34 -0
- package/dist/scroll-progress.js.map +1 -0
- package/dist/select.d.ts +0 -1
- package/dist/select.d.ts.map +1 -1
- package/dist/select.js +2 -4
- package/dist/select.js.map +1 -1
- package/dist/sidebar.d.ts +3 -0
- package/dist/sidebar.d.ts.map +1 -1
- package/dist/sidebar.js +23 -4
- package/dist/sidebar.js.map +1 -1
- package/dist/step-player.d.ts +24 -0
- package/dist/step-player.d.ts.map +1 -0
- package/dist/step-player.js +16 -0
- package/dist/step-player.js.map +1 -0
- package/dist/styles.css +94 -1
- package/dist/styles.layered.css +94 -1
- package/dist/supplemental-display.d.ts +10 -2
- package/dist/supplemental-display.d.ts.map +1 -1
- package/dist/supplemental-display.js +2 -2
- package/dist/supplemental-display.js.map +1 -1
- package/dist/supplemental-navigation.js +1 -1
- package/dist/supplemental-navigation.js.map +1 -1
- package/dist/table-sort-button.d.ts +15 -0
- package/dist/table-sort-button.d.ts.map +1 -0
- package/dist/table-sort-button.js +7 -0
- package/dist/table-sort-button.js.map +1 -0
- package/dist/task-list.d.ts +16 -0
- package/dist/task-list.d.ts.map +1 -0
- package/dist/task-list.js +17 -0
- package/dist/task-list.js.map +1 -0
- package/dist/thinking-orb.d.ts +1 -1
- package/dist/thinking-orb.d.ts.map +1 -1
- package/dist/thinking-orb.js +4 -4
- package/dist/thinking-orb.js.map +1 -1
- package/dist/voice-note.d.ts +24 -0
- package/dist/voice-note.d.ts.map +1 -0
- package/dist/voice-note.js +13 -0
- package/dist/voice-note.js.map +1 -0
- package/package.json +110 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"advanced-forms.js","sourceRoot":"","sources":["../src/advanced-forms.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n comboboxRecipe,\n selectRecipe,\n type SelectDensity,\n type SelectSize,\n} from \"@hjmds/design-contracts/recipes\";\nimport {\n formRecipe,\n type FormDensity,\n} from \"@hjmds/design-contracts/components/form\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type FormEvent,\n type FormHTMLAttributes,\n type InputHTMLAttributes,\n type KeyboardEvent,\n type ReactNode,\n type SelectHTMLAttributes,\n} from \"react\";\nimport { Field } from \"./forms.js\";\nimport { classNames, composeRefs, useControllableState } from \"./internal.js\";\nimport { AnchoredPortal, useAnchoredPopup } from \"./portal.js\";\n\nfunction useControlId(id: string | undefined, prefix: string): string {\n const generated = useId().replaceAll(\":\", \"\");\n return id ?? `hjm-${prefix}-${generated}`;\n}\n\nexport type SelectOption = Readonly<{\n value: string;\n label: string;\n disabled?: boolean;\n}>;\n\nfunction validateOptions(options: readonly SelectOption[], component: string): void {\n if (options.length === 0) throw new TypeError(`${component} requires at least one option`);\n const values = new Set<string>();\n for (const option of options) {\n if (option.value.trim().length === 0) {\n throw new TypeError(`${component} option value must not be empty`);\n }\n if (option.label.trim().length === 0) {\n throw new TypeError(`${component} option label must not be empty`);\n }\n if (values.has(option.value)) {\n throw new TypeError(`Duplicate ${component} option value: ${option.value}`);\n }\n values.add(option.value);\n }\n}\n\nexport type NativeSelectProps = Omit<\n SelectHTMLAttributes<HTMLSelectElement>,\n \"children\" | \"defaultValue\" | \"onChange\" | \"size\" | \"value\"\n> &\n Readonly<{\n label: ReactNode;\n description?: ReactNode;\n error?: ReactNode;\n options: readonly SelectOption[];\n placeholder?: string;\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n size?: SelectSize;\n density?: SelectDensity;\n fieldClassName?: string;\n }>;\n\n/** A native select keeps browser keyboard, form, autofill, and mobile picker behavior. */\nexport const NativeSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(function NativeSelect(\n {\n id,\n label,\n description,\n error,\n options,\n placeholder,\n value: valueProp,\n defaultValue = \"\",\n onValueChange,\n size = selectRecipe.defaults.size,\n density = selectRecipe.defaults.density,\n fieldClassName,\n className,\n disabled = false,\n required = false,\n ...props\n },\n ref,\n) {\n validateOptions(options, \"Select\");\n const controlId = useControlId(id, \"select\");\n const [value, setValue] = useControllableState({\n ...(valueProp === undefined ? {} : { value: valueProp }),\n defaultValue,\n ...(onValueChange === undefined ? {} : { onChange: onValueChange }),\n });\n if (\n value !== \"\" &&\n !options.some((option) => option.value === value && !option.disabled)\n ) {\n throw new RangeError(`Select value must identify an enabled option: ${value}`);\n }\n\n return (\n <Field\n controlId={controlId}\n label={label}\n description={description}\n error={error}\n required={required}\n disabled={disabled}\n className={classNames(\"hjm-select\", fieldClassName)}\n data-size={size}\n data-density={density}\n >\n {(controlProps) => (\n <div className=\"hjm-field__control hjm-select__control\">\n <select\n {...props}\n {...controlProps}\n ref={ref}\n value={value}\n className={classNames(\"hjm-field__input hjm-select__native\", className)}\n onChange={(event: ChangeEvent<HTMLSelectElement>) => setValue(event.target.value)}\n >\n {placeholder !== undefined ? (\n <option value=\"\" disabled={required}>\n {placeholder}\n </option>\n ) : null}\n {options.map((option) => (\n <option key={option.value} value={option.value} disabled={option.disabled}>\n {option.label}\n </option>\n ))}\n </select>\n <span className=\"hjm-select__indicator\" aria-hidden=\"true\">⌄</span>\n </div>\n )}\n </Field>\n );\n});\n\nexport type ComboboxItem = Readonly<{\n value: string;\n label: string;\n keywords?: readonly string[];\n disabled?: boolean;\n}>;\n\nexport type ComboboxOpenChangeReason =\n | \"focus\"\n | \"input\"\n | \"keyboard\"\n | \"selection\"\n | \"escape\"\n | \"blur\";\n\nexport type ComboboxProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"children\" | \"defaultValue\" | \"onChange\" | \"role\" | \"size\" | \"value\"\n> &\n Readonly<{\n label: ReactNode;\n description?: ReactNode;\n error?: ReactNode;\n items: readonly ComboboxItem[];\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n inputValue?: string;\n defaultInputValue?: string;\n onInputValueChange?: (value: string) => void;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean, reason: ComboboxOpenChangeReason) => void;\n /** Localized content rendered when filtering returns no items. */\n emptyMessage: ReactNode;\n loading?: boolean;\n /** Localized content announced while options are loading. */\n loadingMessage: ReactNode;\n /** Localized native-validation message for an empty required selection. */\n selectionRequiredMessage: string;\n openOnFocus?: boolean;\n size?: SelectSize;\n density?: SelectDensity;\n /** Logical listbox alignment against the input; automatically mirrors in RTL. */\n align?: \"start\" | \"end\";\n fieldClassName?: string;\n portalContainer?: HTMLElement;\n }>;\n\nfunction nextEnabled(\n items: readonly ComboboxItem[],\n current: number,\n direction: 1 | -1,\n): number {\n if (items.length === 0) return -1;\n for (let offset = 1; offset <= items.length; offset += 1) {\n const candidate = (current + direction * offset + items.length) % items.length;\n if (!items[candidate]?.disabled) return candidate;\n }\n return -1;\n}\n\nexport const Combobox = forwardRef<HTMLInputElement, ComboboxProps>(\n function Combobox(\n {\n id,\n name,\n label,\n description,\n error,\n items,\n value: valueProp,\n defaultValue = \"\",\n onValueChange,\n inputValue: inputValueProp,\n defaultInputValue,\n onInputValueChange,\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n emptyMessage,\n loading = false,\n loadingMessage,\n selectionRequiredMessage,\n openOnFocus = true,\n size = comboboxRecipe.defaults.size,\n density = comboboxRecipe.defaults.density,\n align = \"start\",\n fieldClassName,\n portalContainer,\n className,\n disabled = false,\n required = false,\n autoComplete = \"off\",\n onFocus,\n onBlur,\n onKeyDown,\n ...props\n },\n forwardedRef,\n ) {\n validateOptions(items, \"Combobox\");\n const controlId = useControlId(id, \"combobox\");\n const listboxId = `${controlId}-listbox`;\n const rootRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const suppressFocusOpenRef = useRef(false);\n const listboxRef = useRef<HTMLDivElement>(null);\n const [listboxNode, setListboxNode] = useState<HTMLDivElement | null>(null);\n const popupPosition = useAnchoredPopup(inputRef, listboxNode, {\n align,\n matchAnchorWidth: true,\n zIndex: 800,\n });\n const setListboxRef = useCallback((node: HTMLDivElement | null) => {\n listboxRef.current = node;\n setListboxNode(node);\n }, []);\n const [selectedValue, setSelectedValue] = useControllableState({\n ...(valueProp === undefined ? {} : { value: valueProp }),\n defaultValue,\n ...(onValueChange === undefined ? {} : { onChange: onValueChange }),\n });\n const selectedItem = items.find((item) => item.value === selectedValue);\n if (selectedValue !== \"\" && (!selectedItem || selectedItem.disabled)) {\n throw new RangeError(\n `Combobox value must identify an enabled option: ${selectedValue}`,\n );\n }\n if (required && selectionRequiredMessage.trim().length === 0) {\n throw new TypeError(\"Combobox selectionRequiredMessage must not be empty\");\n }\n const [query, setQuery] = useControllableState({\n ...(inputValueProp === undefined ? {} : { value: inputValueProp }),\n defaultValue: defaultInputValue ?? selectedItem?.label ?? \"\",\n ...(onInputValueChange === undefined ? {} : { onChange: onInputValueChange }),\n });\n const [open, setOpenState] = useControllableState({\n ...(openProp === undefined ? {} : { value: openProp }),\n defaultValue: defaultOpen,\n });\n const [activeIndex, setActiveIndex] = useState(-1);\n useEffect(() => {\n inputRef.current?.setCustomValidity(\n required && selectedValue === \"\" ? selectionRequiredMessage : \"\",\n );\n }, [required, selectedValue, selectionRequiredMessage]);\n const normalizedQuery = query.trim().toLocaleLowerCase();\n const filteredItems = useMemo(\n () =>\n items.filter((item) => {\n if (normalizedQuery.length === 0) return true;\n const searchable = [item.label, ...(item.keywords ?? [])]\n .join(\" \")\n .toLocaleLowerCase();\n return searchable.includes(normalizedQuery);\n }),\n [items, normalizedQuery],\n );\n\n const setOpen = (next: boolean, reason: ComboboxOpenChangeReason) => {\n if (next === open) return;\n setOpenState(next);\n onOpenChange?.(next, reason);\n if (!next) setActiveIndex(-1);\n };\n const firstEnabled = () => filteredItems.findIndex((item) => !item.disabled);\n const lastEnabled = () => {\n for (let index = filteredItems.length - 1; index >= 0; index -= 1) {\n if (!filteredItems[index]?.disabled) return index;\n }\n return -1;\n };\n const selectItem = (item: ComboboxItem) => {\n if (item.disabled) return;\n setSelectedValue(item.value);\n setQuery(item.label);\n setOpen(false, \"selection\");\n queueMicrotask(() => {\n const input = inputRef.current;\n if (!input || document.activeElement === input) return;\n suppressFocusOpenRef.current = true;\n input.focus();\n queueMicrotask(() => {\n suppressFocusOpenRef.current = false;\n });\n });\n };\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented) return;\n if (\n loading &&\n [\"ArrowDown\", \"ArrowUp\", \"Home\", \"End\", \"Enter\"].includes(event.key)\n ) {\n event.preventDefault();\n return;\n }\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n if (!open) {\n setOpen(true, \"keyboard\");\n setActiveIndex(\n event.key === \"ArrowDown\" ? firstEnabled() : lastEnabled(),\n );\n return;\n }\n setActiveIndex((current) =>\n nextEnabled(filteredItems, current, event.key === \"ArrowDown\" ? 1 : -1),\n );\n } else if (open && event.key === \"Home\") {\n event.preventDefault();\n setActiveIndex(firstEnabled());\n } else if (open && event.key === \"End\") {\n event.preventDefault();\n setActiveIndex(lastEnabled());\n } else if (open && event.key === \"Enter\" && activeIndex >= 0) {\n event.preventDefault();\n const item = filteredItems[activeIndex];\n if (item) selectItem(item);\n } else if (open && event.key === \"Escape\") {\n event.preventDefault();\n setOpen(false, \"escape\");\n } else if (open && event.key === \"Tab\") {\n setOpen(false, \"blur\");\n }\n };\n const activeItem = activeIndex >= 0 ? filteredItems[activeIndex] : undefined;\n\n return (\n <Field\n controlId={controlId}\n label={label}\n description={description}\n error={error}\n required={required}\n disabled={disabled}\n className={classNames(\"hjm-combobox\", fieldClassName)}\n data-size={size}\n data-density={density}\n data-state={disabled ? \"disabled\" : open ? \"open\" : \"closed\"}\n >\n {(controlProps) => (\n <div\n ref={rootRef}\n className=\"hjm-combobox__anchor\"\n onBlur={(event) => {\n if (\n !event.currentTarget.contains(event.relatedTarget) &&\n !listboxRef.current?.contains(event.relatedTarget)\n ) setOpen(false, \"blur\");\n }}\n >\n <div className=\"hjm-field__control hjm-combobox__control\">\n <input\n {...props}\n {...controlProps}\n ref={composeRefs(forwardedRef, inputRef)}\n className={classNames(\"hjm-field__input hjm-combobox__input\", className)}\n value={query}\n role=\"combobox\"\n autoComplete={autoComplete}\n aria-autocomplete=\"list\"\n aria-controls={listboxId}\n aria-expanded={open}\n aria-activedescendant={\n open && activeItem ? `${controlId}-option-${activeIndex}` : undefined\n }\n onFocus={(event) => {\n onFocus?.(event);\n if (\n !event.defaultPrevented &&\n openOnFocus &&\n !suppressFocusOpenRef.current\n ) setOpen(true, \"focus\");\n }}\n onBlur={onBlur}\n onChange={(event) => {\n setQuery(event.target.value);\n setSelectedValue(\"\");\n setOpen(true, \"input\");\n setActiveIndex(-1);\n }}\n onKeyDown={handleKeyDown}\n />\n {loading ? <span className=\"hjm-combobox__spinner\" aria-hidden=\"true\" /> : null}\n <span className=\"hjm-select__indicator\" aria-hidden=\"true\">⌄</span>\n </div>\n {name ? <input type=\"hidden\" name={name} value={selectedValue} /> : null}\n {open ? (\n <AnchoredPortal\n anchorRef={inputRef}\n ssrFallback=\"inline\"\n {...(portalContainer === undefined ? {} : { container: portalContainer })}\n >\n <div\n ref={setListboxRef}\n id={listboxId}\n role=\"listbox\"\n className=\"hjm-combobox__listbox\"\n data-density={density}\n aria-label={typeof label === \"string\" ? label : undefined}\n aria-busy={loading || undefined}\n data-placement={popupPosition.placement}\n data-align={popupPosition.align}\n style={popupPosition.style}\n >\n {loading ? (\n <div className=\"hjm-combobox__message\" role=\"status\">{loadingMessage}</div>\n ) : filteredItems.length === 0 ? (\n <div className=\"hjm-combobox__message\">{emptyMessage}</div>\n ) : (\n filteredItems.map((item, index) => (\n <div\n key={item.value}\n id={`${controlId}-option-${index}`}\n role=\"option\"\n aria-selected={item.value === selectedValue}\n aria-disabled={item.disabled || undefined}\n className=\"hjm-combobox__option\"\n data-state={\n item.disabled\n ? \"disabled\"\n : index === activeIndex\n ? \"active\"\n : item.value === selectedValue\n ? \"selected\"\n : \"idle\"\n }\n onMouseDown={(event) => event.preventDefault()}\n onMouseMove={() => {\n if (!item.disabled) setActiveIndex(index);\n }}\n onClick={() => selectItem(item)}\n >\n {item.label}\n </div>\n ))\n )}\n </div>\n </AnchoredPortal>\n ) : null}\n </div>\n )}\n </Field>\n );\n },\n);\n\nexport type FormSubmitHandler = (\n event: FormEvent<HTMLFormElement>,\n) => void | Promise<void>;\n\nexport type FormProps = Omit<FormHTMLAttributes<HTMLFormElement>, \"onSubmit\"> &\n Readonly<{\n onSubmit: FormSubmitHandler;\n busy?: boolean;\n formError?: ReactNode;\n actions?: ReactNode;\n density?: FormDensity;\n }>;\n\nexport const Form = forwardRef<HTMLFormElement, FormProps>(function Form(\n {\n onSubmit,\n busy = false,\n formError,\n actions,\n density = formRecipe.defaults.density,\n className,\n children,\n ...props\n },\n ref,\n) {\n const [submitting, setSubmitting] = useState(false);\n const submittingRef = useRef(false);\n const effectiveBusy = busy || submitting;\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (effectiveBusy || submittingRef.current) return;\n let result: void | Promise<void>;\n try {\n result = onSubmit(event);\n } catch (error) {\n throw error;\n }\n if (result && typeof result.then === \"function\") {\n submittingRef.current = true;\n setSubmitting(true);\n void Promise.resolve(result)\n .catch(() => undefined)\n .finally(() => {\n submittingRef.current = false;\n setSubmitting(false);\n });\n }\n };\n\n return (\n <form\n {...props}\n ref={ref}\n className={classNames(\"hjm-form\", className)}\n data-density={density}\n data-state={effectiveBusy ? \"busy\" : formError ? \"error\" : \"idle\"}\n aria-busy={effectiveBusy || undefined}\n onSubmit={handleSubmit}\n >\n <fieldset className=\"hjm-form__fieldset\" disabled={effectiveBusy}>\n <div className=\"hjm-form__fields\">{children}</div>\n {formError ? (\n <div className=\"hjm-form__error\" role=\"alert\">{formError}</div>\n ) : null}\n {actions ? <div className=\"hjm-form__actions\">{actions}</div> : null}\n </fieldset>\n </form>\n );\n});\n"]}
|
|
1
|
+
{"version":3,"file":"advanced-forms.js","sourceRoot":"","sources":["../src/advanced-forms.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n comboboxRecipe,\n selectRecipe,\n type SelectDensity,\n type SelectSize,\n} from \"@hjmds/design-contracts/recipes\";\nimport {\n formRecipe,\n type FormDensity,\n} from \"@hjmds/design-contracts/components/form\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type FormEvent,\n type FormHTMLAttributes,\n type InputHTMLAttributes,\n type KeyboardEvent,\n type ReactNode,\n type SelectHTMLAttributes,\n} from \"react\";\nimport { Field } from \"./forms.js\";\nimport { classNames, composeRefs, useControllableState } from \"./internal.js\";\nimport { AnchoredPortal, useAnchoredPopup } from \"./portal.js\";\n\nfunction useControlId(id: string | undefined, prefix: string): string {\n const generated = useId().replaceAll(\":\", \"\");\n return id ?? `hjm-${prefix}-${generated}`;\n}\n\nexport type SelectOption = Readonly<{\n value: string;\n label: string;\n disabled?: boolean;\n}>;\n\nfunction validateOptions(options: readonly SelectOption[], component: string): void {\n if (options.length === 0) throw new TypeError(`${component} requires at least one option`);\n const values = new Set<string>();\n for (const option of options) {\n if (option.value.trim().length === 0) {\n throw new TypeError(`${component} option value must not be empty`);\n }\n if (option.label.trim().length === 0) {\n throw new TypeError(`${component} option label must not be empty`);\n }\n if (values.has(option.value)) {\n throw new TypeError(`Duplicate ${component} option value: ${option.value}`);\n }\n values.add(option.value);\n }\n}\n\nexport type NativeSelectProps = Omit<\n SelectHTMLAttributes<HTMLSelectElement>,\n \"children\" | \"defaultValue\" | \"onChange\" | \"size\" | \"value\"\n> &\n Readonly<{\n label: ReactNode;\n description?: ReactNode;\n error?: ReactNode;\n options: readonly SelectOption[];\n placeholder?: string;\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n size?: SelectSize;\n density?: SelectDensity;\n fieldClassName?: string;\n }>;\n\n/** A native select keeps browser keyboard, form, autofill, and mobile picker behavior. */\nexport const NativeSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(function NativeSelect(\n {\n id,\n label,\n description,\n error,\n options,\n placeholder,\n value: valueProp,\n defaultValue = \"\",\n onValueChange,\n size = selectRecipe.defaults.size,\n density = selectRecipe.defaults.density,\n fieldClassName,\n className,\n disabled = false,\n required = false,\n ...props\n },\n ref,\n) {\n validateOptions(options, \"Select\");\n const controlId = useControlId(id, \"select\");\n const [value, setValue] = useControllableState({\n ...(valueProp === undefined ? {} : { value: valueProp }),\n defaultValue,\n ...(onValueChange === undefined ? {} : { onChange: onValueChange }),\n });\n if (\n value !== \"\" &&\n !options.some((option) => option.value === value && !option.disabled)\n ) {\n throw new RangeError(`Select value must identify an enabled option: ${value}`);\n }\n\n return (\n <Field\n controlId={controlId}\n label={label}\n description={description}\n error={error}\n required={required}\n disabled={disabled}\n className={classNames(\"hjm-select\", fieldClassName)}\n data-size={size}\n data-density={density}\n >\n {(controlProps) => (\n <div className=\"hjm-field__control hjm-select__control\">\n <select\n {...props}\n {...controlProps}\n ref={ref}\n value={value}\n className={classNames(\"hjm-field__input hjm-select__native\", className)}\n onChange={(event: ChangeEvent<HTMLSelectElement>) => setValue(event.target.value)}\n >\n {placeholder !== undefined ? (\n <option value=\"\" disabled={required}>\n {placeholder}\n </option>\n ) : null}\n {options.map((option) => (\n <option key={option.value} value={option.value} disabled={option.disabled}>\n {option.label}\n </option>\n ))}\n </select>\n <span className=\"hjm-select__indicator\" aria-hidden=\"true\">⌄</span>\n </div>\n )}\n </Field>\n );\n});\n\nexport type ComboboxItem = Readonly<{\n value: string;\n label: string;\n keywords?: readonly string[];\n disabled?: boolean;\n}>;\n\nexport type ComboboxOpenChangeReason =\n | \"focus\"\n | \"input\"\n | \"keyboard\"\n | \"selection\"\n | \"escape\"\n | \"blur\";\n\nexport type ComboboxProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"children\" | \"defaultValue\" | \"onChange\" | \"role\" | \"size\" | \"value\"\n> &\n Readonly<{\n label: ReactNode;\n description?: ReactNode;\n error?: ReactNode;\n items: readonly ComboboxItem[];\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n inputValue?: string;\n defaultInputValue?: string;\n onInputValueChange?: (value: string) => void;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean, reason: ComboboxOpenChangeReason) => void;\n /** Localized content rendered when filtering returns no items. */\n emptyMessage: ReactNode;\n loading?: boolean;\n /** Localized content announced while options are loading. */\n loadingMessage: ReactNode;\n /** Localized native-validation message for an empty required selection. */\n selectionRequiredMessage: string;\n openOnFocus?: boolean;\n size?: SelectSize;\n density?: SelectDensity;\n /** Logical listbox alignment against the input; automatically mirrors in RTL. */\n align?: \"start\" | \"end\";\n fieldClassName?: string;\n portalContainer?: HTMLElement;\n }>;\n\nfunction nextEnabled(\n items: readonly ComboboxItem[],\n current: number,\n direction: 1 | -1,\n): number {\n if (items.length === 0) return -1;\n for (let offset = 1; offset <= items.length; offset += 1) {\n const candidate = (current + direction * offset + items.length) % items.length;\n if (!items[candidate]?.disabled) return candidate;\n }\n return -1;\n}\n\nexport const Combobox = forwardRef<HTMLInputElement, ComboboxProps>(\n function Combobox(\n {\n id,\n name,\n label,\n description,\n error,\n items,\n value: valueProp,\n defaultValue = \"\",\n onValueChange,\n inputValue: inputValueProp,\n defaultInputValue,\n onInputValueChange,\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n emptyMessage,\n loading = false,\n loadingMessage,\n selectionRequiredMessage,\n openOnFocus = true,\n size = comboboxRecipe.defaults.size,\n density = comboboxRecipe.defaults.density,\n align = \"start\",\n fieldClassName,\n portalContainer,\n className,\n disabled = false,\n required = false,\n autoComplete = \"off\",\n onFocus,\n onBlur,\n onKeyDown,\n ...props\n },\n forwardedRef,\n ) {\n validateOptions(items, \"Combobox\");\n const controlId = useControlId(id, \"combobox\");\n const listboxId = `${controlId}-listbox`;\n const rootRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const suppressFocusOpenRef = useRef(false);\n const listboxRef = useRef<HTMLDivElement>(null);\n const [listboxNode, setListboxNode] = useState<HTMLDivElement | null>(null);\n const popupPosition = useAnchoredPopup(inputRef, listboxNode, {\n align,\n matchAnchorWidth: true,\n zIndex: 800,\n });\n const setListboxRef = useCallback((node: HTMLDivElement | null) => {\n listboxRef.current = node;\n setListboxNode(node);\n }, []);\n const [selectedValue, setSelectedValue] = useControllableState({\n ...(valueProp === undefined ? {} : { value: valueProp }),\n defaultValue,\n ...(onValueChange === undefined ? {} : { onChange: onValueChange }),\n });\n const selectedItem = items.find((item) => item.value === selectedValue);\n if (selectedValue !== \"\" && (!selectedItem || selectedItem.disabled)) {\n throw new RangeError(\n `Combobox value must identify an enabled option: ${selectedValue}`,\n );\n }\n if (required && selectionRequiredMessage.trim().length === 0) {\n throw new TypeError(\"Combobox selectionRequiredMessage must not be empty\");\n }\n const [query, setQuery] = useControllableState({\n ...(inputValueProp === undefined ? {} : { value: inputValueProp }),\n defaultValue: defaultInputValue ?? selectedItem?.label ?? \"\",\n ...(onInputValueChange === undefined ? {} : { onChange: onInputValueChange }),\n });\n const [open, setOpenState] = useControllableState({\n ...(openProp === undefined ? {} : { value: openProp }),\n defaultValue: defaultOpen,\n });\n const [activeIndex, setActiveIndex] = useState(-1);\n useEffect(() => {\n inputRef.current?.setCustomValidity(\n required && selectedValue === \"\" ? selectionRequiredMessage : \"\",\n );\n }, [required, selectedValue, selectionRequiredMessage]);\n const normalizedQuery = query.trim().toLocaleLowerCase();\n const filteredItems = useMemo(\n () =>\n items.filter((item) => {\n if (normalizedQuery.length === 0) return true;\n const searchable = [item.label, ...(item.keywords ?? [])]\n .join(\" \")\n .toLocaleLowerCase();\n return searchable.includes(normalizedQuery);\n }),\n [items, normalizedQuery],\n );\n\n const setOpen = (next: boolean, reason: ComboboxOpenChangeReason) => {\n if (next === open) return;\n setOpenState(next);\n onOpenChange?.(next, reason);\n if (!next) setActiveIndex(-1);\n };\n const firstEnabled = () => filteredItems.findIndex((item) => !item.disabled);\n const lastEnabled = () => {\n for (let index = filteredItems.length - 1; index >= 0; index -= 1) {\n if (!filteredItems[index]?.disabled) return index;\n }\n return -1;\n };\n const selectItem = (item: ComboboxItem) => {\n if (item.disabled) return;\n setSelectedValue(item.value);\n setQuery(item.label);\n setOpen(false, \"selection\");\n queueMicrotask(() => {\n const input = inputRef.current;\n if (!input || document.activeElement === input) return;\n suppressFocusOpenRef.current = true;\n input.focus();\n queueMicrotask(() => {\n suppressFocusOpenRef.current = false;\n });\n });\n };\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented) return;\n if (\n loading &&\n [\"ArrowDown\", \"ArrowUp\", \"Home\", \"End\", \"Enter\"].includes(event.key)\n ) {\n event.preventDefault();\n return;\n }\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n if (!open) {\n setOpen(true, \"keyboard\");\n setActiveIndex(\n event.key === \"ArrowDown\" ? firstEnabled() : lastEnabled(),\n );\n return;\n }\n setActiveIndex((current) =>\n nextEnabled(filteredItems, current, event.key === \"ArrowDown\" ? 1 : -1),\n );\n } else if (open && event.key === \"Home\") {\n event.preventDefault();\n setActiveIndex(firstEnabled());\n } else if (open && event.key === \"End\") {\n event.preventDefault();\n setActiveIndex(lastEnabled());\n } else if (open && event.key === \"Enter\" && activeIndex >= 0) {\n event.preventDefault();\n const item = filteredItems[activeIndex];\n if (item) selectItem(item);\n } else if (open && event.key === \"Escape\") {\n event.preventDefault();\n setOpen(false, \"escape\");\n } else if (open && event.key === \"Tab\") {\n setOpen(false, \"blur\");\n }\n };\n const activeItem = activeIndex >= 0 ? filteredItems[activeIndex] : undefined;\n\n return (\n <Field\n controlId={controlId}\n label={label}\n description={description}\n error={error}\n required={required}\n disabled={disabled}\n className={classNames(\"hjm-combobox\", fieldClassName)}\n data-size={size}\n data-density={density}\n data-state={disabled ? \"disabled\" : open ? \"open\" : \"closed\"}\n >\n {(controlProps) => (\n <div\n ref={rootRef}\n className=\"hjm-combobox__anchor\"\n onBlur={(event) => {\n if (\n !event.currentTarget.contains(event.relatedTarget) &&\n !listboxRef.current?.contains(event.relatedTarget)\n ) setOpen(false, \"blur\");\n }}\n >\n <div className=\"hjm-field__control hjm-combobox__control\">\n <input\n {...props}\n {...controlProps}\n ref={composeRefs(forwardedRef, inputRef)}\n className={classNames(\"hjm-field__input hjm-combobox__input\", className)}\n value={query}\n role=\"combobox\"\n autoComplete={autoComplete}\n aria-autocomplete=\"list\"\n aria-controls={listboxId}\n aria-expanded={open}\n aria-activedescendant={\n open && activeItem ? `${controlId}-option-${activeIndex}` : undefined\n }\n onFocus={(event) => {\n onFocus?.(event);\n if (\n !event.defaultPrevented &&\n openOnFocus &&\n !suppressFocusOpenRef.current\n ) setOpen(true, \"focus\");\n }}\n onBlur={onBlur}\n onChange={(event) => {\n setQuery(event.target.value);\n setSelectedValue(\"\");\n setOpen(true, \"input\");\n setActiveIndex(-1);\n }}\n onKeyDown={handleKeyDown}\n />\n {loading ? <span className=\"hjm-combobox__spinner\" aria-hidden=\"true\" /> : null}\n <span className=\"hjm-select__indicator\" aria-hidden=\"true\">⌄</span>\n </div>\n {name ? <input type=\"hidden\" name={name} value={selectedValue} /> : null}\n {open ? (\n <AnchoredPortal\n anchorRef={inputRef}\n ssrFallback=\"inline\"\n {...(portalContainer === undefined ? {} : { container: portalContainer })}\n >\n <div\n ref={setListboxRef}\n id={listboxId}\n role=\"listbox\"\n className=\"hjm-combobox__listbox\"\n data-density={density}\n aria-label={typeof label === \"string\" ? label : undefined}\n aria-busy={loading || undefined}\n data-placement={popupPosition.placement}\n data-align={popupPosition.align}\n style={popupPosition.style}\n >\n {loading ? (\n <div className=\"hjm-combobox__message\" role=\"status\"><span className=\"hjm-visually-hidden\">{loadingMessage}</span></div>\n ) : filteredItems.length === 0 ? (\n <div className=\"hjm-combobox__message\">{emptyMessage}</div>\n ) : (\n filteredItems.map((item, index) => (\n <div\n key={item.value}\n id={`${controlId}-option-${index}`}\n role=\"option\"\n aria-selected={item.value === selectedValue}\n aria-disabled={item.disabled || undefined}\n className=\"hjm-combobox__option\"\n data-state={\n item.disabled\n ? \"disabled\"\n : index === activeIndex\n ? \"active\"\n : item.value === selectedValue\n ? \"selected\"\n : \"idle\"\n }\n onMouseDown={(event) => event.preventDefault()}\n onMouseMove={() => {\n if (!item.disabled) setActiveIndex(index);\n }}\n onClick={() => selectItem(item)}\n >\n {item.label}\n </div>\n ))\n )}\n </div>\n </AnchoredPortal>\n ) : null}\n </div>\n )}\n </Field>\n );\n },\n);\n\nexport type FormSubmitHandler = (\n event: FormEvent<HTMLFormElement>,\n) => void | Promise<void>;\n\nexport type FormProps = Omit<FormHTMLAttributes<HTMLFormElement>, \"onSubmit\"> &\n Readonly<{\n onSubmit: FormSubmitHandler;\n busy?: boolean;\n formError?: ReactNode;\n actions?: ReactNode;\n density?: FormDensity;\n }>;\n\nexport const Form = forwardRef<HTMLFormElement, FormProps>(function Form(\n {\n onSubmit,\n busy = false,\n formError,\n actions,\n density = formRecipe.defaults.density,\n className,\n children,\n ...props\n },\n ref,\n) {\n const [submitting, setSubmitting] = useState(false);\n const submittingRef = useRef(false);\n const effectiveBusy = busy || submitting;\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (effectiveBusy || submittingRef.current) return;\n let result: void | Promise<void>;\n try {\n result = onSubmit(event);\n } catch (error) {\n throw error;\n }\n if (result && typeof result.then === \"function\") {\n submittingRef.current = true;\n setSubmitting(true);\n void Promise.resolve(result)\n .catch(() => undefined)\n .finally(() => {\n submittingRef.current = false;\n setSubmitting(false);\n });\n }\n };\n\n return (\n <form\n {...props}\n ref={ref}\n className={classNames(\"hjm-form\", className)}\n data-density={density}\n data-state={effectiveBusy ? \"busy\" : formError ? \"error\" : \"idle\"}\n aria-busy={effectiveBusy || undefined}\n onSubmit={handleSubmit}\n >\n <fieldset className=\"hjm-form__fieldset\" disabled={effectiveBusy}>\n <div className=\"hjm-form__fields\">{children}</div>\n {formError ? (\n <div className=\"hjm-form__error\" role=\"alert\">{formError}</div>\n ) : null}\n {actions ? <div className=\"hjm-form__actions\">{actions}</div> : null}\n </fieldset>\n </form>\n );\n});\n"]}
|
package/dist/auth-screen.d.ts
CHANGED
|
@@ -7,6 +7,10 @@ export type AuthScreenLayoutProps = Omit<HTMLAttributes<HTMLElement>, "children"
|
|
|
7
7
|
hero: ReactNode;
|
|
8
8
|
/** The primary action block — provider buttons, or a product's own sign-in bundle. */
|
|
9
9
|
main: ReactNode;
|
|
10
|
+
/** Product-localized progress label; presence replaces actions with one centred loader. */
|
|
11
|
+
pendingLabel?: string;
|
|
12
|
+
/** Let the layout own the action card; omit when the product already supplies a surface. */
|
|
13
|
+
mainCard?: boolean;
|
|
10
14
|
/** Consent notice and policy links. Omit with `hasFooter: false`. */
|
|
11
15
|
footer?: ReactNode;
|
|
12
16
|
className?: string;
|
|
@@ -26,6 +30,10 @@ export declare const AuthScreenLayout: import("react").ForwardRefExoticComponent
|
|
|
26
30
|
hero: ReactNode;
|
|
27
31
|
/** The primary action block — provider buttons, or a product's own sign-in bundle. */
|
|
28
32
|
main: ReactNode;
|
|
33
|
+
/** Product-localized progress label; presence replaces actions with one centred loader. */
|
|
34
|
+
pendingLabel?: string;
|
|
35
|
+
/** Let the layout own the action card; omit when the product already supplies a surface. */
|
|
36
|
+
mainCard?: boolean;
|
|
29
37
|
/** Consent notice and policy links. Omit with `hasFooter: false`. */
|
|
30
38
|
footer?: ReactNode;
|
|
31
39
|
className?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-screen.d.ts","sourceRoot":"","sources":["../src/auth-screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,gDAAgD,CAAC;AACxD,OAAO,EAAc,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGxE,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC,GAC/E,oBAAoB,GACpB,QAAQ,CAAC;IACP,8EAA8E;IAC9E,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,+EAA+E;IAC/E,IAAI,EAAE,SAAS,CAAC;IAChB,sFAAsF;IACtF,IAAI,EAAE,SAAS,CAAC;IAChB,qEAAqE;IACrE,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,CAAC;AAEL;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;;;
|
|
1
|
+
{"version":3,"file":"auth-screen.d.ts","sourceRoot":"","sources":["../src/auth-screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,gDAAgD,CAAC;AACxD,OAAO,EAAc,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGxE,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC,GAC/E,oBAAoB,GACpB,QAAQ,CAAC;IACP,8EAA8E;IAC9E,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,+EAA+E;IAC/E,IAAI,EAAE,SAAS,CAAC;IAChB,sFAAsF;IACtF,IAAI,EAAE,SAAS,CAAC;IAChB,2FAA2F;IAC3F,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qEAAqE;IACrE,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,CAAC;AAEL;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;;;IApBzB,8EAA8E;SACzE,MAAM,GAAG,SAAS;IACvB,+EAA+E;UACzE,SAAS;IACf,sFAAsF;UAChF,SAAS;IACf,2FAA2F;mBAC5E,MAAM;IACrB,4FAA4F;eACjF,OAAO;IAClB,qEAAqE;aAC5D,SAAS;gBACN,MAAM;gDAmDrB,CAAC"}
|
package/dist/auth-screen.js
CHANGED
|
@@ -7,12 +7,15 @@ import { classNames } from "./internal.js";
|
|
|
7
7
|
* the bottom. The measurements come from the resolved descriptor as custom
|
|
8
8
|
* properties so the stylesheet keeps one source of truth with the contract.
|
|
9
9
|
*/
|
|
10
|
-
export const AuthScreenLayout = forwardRef(function AuthScreenLayout({ hero, main, footer, density, hasFooter, className, as: Element = "main", ...props }, forwardedRef) {
|
|
10
|
+
export const AuthScreenLayout = forwardRef(function AuthScreenLayout({ hero, main, footer, density, hasFooter, pendingLabel, mainCard = false, className, as: Element = "main", ...props }, forwardedRef) {
|
|
11
11
|
const resolved = resolveAuthScreenDescriptor({
|
|
12
12
|
...(density === undefined ? {} : { density }),
|
|
13
13
|
...(hasFooter === undefined ? {} : { hasFooter }),
|
|
14
14
|
});
|
|
15
15
|
const showFooter = resolved.hasFooter && footer !== undefined && footer !== null;
|
|
16
|
+
const pending = pendingLabel !== undefined;
|
|
17
|
+
if (pending && !pendingLabel.trim())
|
|
18
|
+
throw new TypeError("AuthScreen pendingLabel must not be empty");
|
|
16
19
|
return (_jsxs(Element, { ...props, ref: forwardedRef, className: classNames("hjm-auth-screen", className), "data-density": resolved.density, style: {
|
|
17
20
|
["--hjm-auth-screen-max-width"]: `${resolved.maxWidth}px`,
|
|
18
21
|
["--hjm-auth-screen-hero-gap"]: `${resolved.heroGap}px`,
|
|
@@ -21,6 +24,6 @@ export const AuthScreenLayout = forwardRef(function AuthScreenLayout({ hero, mai
|
|
|
21
24
|
["--hjm-auth-screen-padding-inline"]: `${resolved.paddingInline}px`,
|
|
22
25
|
["--hjm-auth-screen-padding-block"]: `${resolved.paddingBlock}px`,
|
|
23
26
|
...props.style,
|
|
24
|
-
}, children: [_jsxs("div", { className: "hjm-auth-screen__block", children: [_jsx("div", { className: "hjm-auth-screen__hero", children: hero }),
|
|
27
|
+
}, children: [_jsxs("div", { className: "hjm-auth-screen__block", children: [_jsx("div", { className: "hjm-auth-screen__hero", children: hero }), _jsxs("div", { className: "hjm-auth-screen__main", "data-card": mainCard || undefined, "aria-busy": pending || undefined, children: [_jsx("div", { className: "hjm-auth-screen__actions", inert: pending, "aria-hidden": pending || undefined, style: pending ? { visibility: "hidden" } : undefined, children: main }), pending ? _jsx("div", { className: "hjm-auth-screen__pending", role: "status", "aria-label": pendingLabel, children: _jsx("span", { className: "hjm-auth-provider-button__spinner", "aria-hidden": "true" }) }) : null] })] }), showFooter ? _jsx("div", { className: "hjm-auth-screen__footer", children: footer }) : null] }));
|
|
25
28
|
});
|
|
26
29
|
//# sourceMappingURL=auth-screen.js.map
|
package/dist/auth-screen.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-screen.js","sourceRoot":"","sources":["../src/auth-screen.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,2BAA2B,GAE5B,MAAM,gDAAgD,CAAC;AACxD,OAAO,EAAE,UAAU,EAAuC,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"auth-screen.js","sourceRoot":"","sources":["../src/auth-screen.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,2BAA2B,GAE5B,MAAM,gDAAgD,CAAC;AACxD,OAAO,EAAE,UAAU,EAAuC,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAoB3C;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CACxC,SAAS,gBAAgB,CACvB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,GAAG,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,KAAK,EAAE,EACrH,YAAY;IAEZ,MAAM,QAAQ,GAAG,2BAA2B,CAAC;QAC3C,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;QAC7C,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC;KAClD,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,QAAQ,CAAC,SAAS,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,CAAC;IACjF,MAAM,OAAO,GAAG,YAAY,KAAK,SAAS,CAAC;IAC3C,IAAI,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,SAAS,CAAC,2CAA2C,CAAC,CAAC;IACtG,OAAO,CACL,MAAC,OAAO,OACF,KAAK,EACT,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,UAAU,CAAC,iBAAiB,EAAE,SAAS,CAAC,kBACrC,QAAQ,CAAC,OAAO,EAC9B,KAAK,EAAE;YACL,CAAC,6BAAuC,CAAC,EAAE,GAAG,QAAQ,CAAC,QAAQ,IAAI;YACnE,CAAC,4BAAsC,CAAC,EAAE,GAAG,QAAQ,CAAC,OAAO,IAAI;YACjE,CAAC,4BAAsC,CAAC,EAAE,GAAG,QAAQ,CAAC,OAAO,IAAI;YACjE,CAAC,8BAAwC,CAAC,EAAE,GAAG,QAAQ,CAAC,SAAS,IAAI;YACrE,CAAC,kCAA4C,CAAC,EAAE,GAAG,QAAQ,CAAC,aAAa,IAAI;YAC7E,CAAC,iCAA2C,CAAC,EAAE,GAAG,QAAQ,CAAC,YAAY,IAAI;YAC3E,GAAG,KAAK,CAAC,KAAK;SACf,aAED,eAAK,SAAS,EAAC,wBAAwB,aACrC,cAAK,SAAS,EAAC,uBAAuB,YAAE,IAAI,GAAO,EACnD,eAAK,SAAS,EAAC,uBAAuB,eAAY,QAAQ,IAAI,SAAS,eAAa,OAAO,IAAI,SAAS,aAEtG,cAAK,SAAS,EAAC,0BAA0B,EAAC,KAAK,EAAE,OAAO,iBAAe,OAAO,IAAI,SAAS,EACzF,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS,YAAG,IAAI,GAAO,EACpE,OAAO,CAAC,CAAC,CAAC,cAAK,SAAS,EAAC,0BAA0B,EAAC,IAAI,EAAC,QAAQ,gBAAa,YAAY,YACzF,eAAM,SAAS,EAAC,mCAAmC,iBAAa,MAAM,GAAG,GACrE,CAAC,CAAC,CAAC,IAAI,IACT,IACF,EACL,UAAU,CAAC,CAAC,CAAC,cAAK,SAAS,EAAC,yBAAyB,YAAE,MAAM,GAAO,CAAC,CAAC,CAAC,IAAI,IACpE,CACX,CAAC;AACJ,CAAC,CACF,CAAC","sourcesContent":["import {\n resolveAuthScreenDescriptor,\n type AuthScreenDescriptor,\n} from \"@hjmds/design-contracts/components/auth-screen\";\nimport { forwardRef, type HTMLAttributes, type ReactNode } from \"react\";\nimport { classNames } from \"./internal.js\";\n\nexport type AuthScreenLayoutProps = Omit<HTMLAttributes<HTMLElement>, \"children\"> &\n AuthScreenDescriptor &\n Readonly<{\n /** Use section inside a product shell that already owns the main landmark. */\n as?: \"main\" | \"section\";\n /** Product mark, title and description. The product owns every string here. */\n hero: ReactNode;\n /** The primary action block — provider buttons, or a product's own sign-in bundle. */\n main: ReactNode;\n /** Product-localized progress label; presence replaces actions with one centred loader. */\n pendingLabel?: string;\n /** Let the layout own the action card; omit when the product already supplies a surface. */\n mainCard?: boolean;\n /** Consent notice and policy links. Omit with `hasFooter: false`. */\n footer?: ReactNode;\n className?: string;\n }>;\n\n/**\n * Two regions: hero + main stay one vertically centred block, the footer sits at\n * the bottom. The measurements come from the resolved descriptor as custom\n * properties so the stylesheet keeps one source of truth with the contract.\n */\nexport const AuthScreenLayout = forwardRef<HTMLElement, AuthScreenLayoutProps>(\n function AuthScreenLayout(\n { hero, main, footer, density, hasFooter, pendingLabel, mainCard = false, className, as: Element = \"main\", ...props },\n forwardedRef,\n ) {\n const resolved = resolveAuthScreenDescriptor({\n ...(density === undefined ? {} : { density }),\n ...(hasFooter === undefined ? {} : { hasFooter }),\n });\n const showFooter = resolved.hasFooter && footer !== undefined && footer !== null;\n const pending = pendingLabel !== undefined;\n if (pending && !pendingLabel.trim()) throw new TypeError(\"AuthScreen pendingLabel must not be empty\");\n return (\n <Element\n {...props}\n ref={forwardedRef}\n className={classNames(\"hjm-auth-screen\", className)}\n data-density={resolved.density}\n style={{\n [\"--hjm-auth-screen-max-width\" as string]: `${resolved.maxWidth}px`,\n [\"--hjm-auth-screen-hero-gap\" as string]: `${resolved.heroGap}px`,\n [\"--hjm-auth-screen-main-gap\" as string]: `${resolved.mainGap}px`,\n [\"--hjm-auth-screen-footer-gap\" as string]: `${resolved.footerGap}px`,\n [\"--hjm-auth-screen-padding-inline\" as string]: `${resolved.paddingInline}px`,\n [\"--hjm-auth-screen-padding-block\" as string]: `${resolved.paddingBlock}px`,\n ...props.style,\n }}\n >\n <div className=\"hjm-auth-screen__block\">\n <div className=\"hjm-auth-screen__hero\">{hero}</div>\n <div className=\"hjm-auth-screen__main\" data-card={mainCard || undefined} aria-busy={pending || undefined}>\n {/* Keep the action block in flow so the card never collapses; inert also removes keyboard access. */}\n <div className=\"hjm-auth-screen__actions\" inert={pending} aria-hidden={pending || undefined}\n style={pending ? { visibility: \"hidden\" } : undefined}>{main}</div>\n {pending ? <div className=\"hjm-auth-screen__pending\" role=\"status\" aria-label={pendingLabel}>\n <span className=\"hjm-auth-provider-button__spinner\" aria-hidden=\"true\" />\n </div> : null}\n </div>\n </div>\n {showFooter ? <div className=\"hjm-auth-screen__footer\">{footer}</div> : null}\n </Element>\n );\n },\n);\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import 'blobatar/motion.css';
|
|
3
|
+
import { type BlobatarMotionOptions, type AvatarFallbackContext } from '@hjmds/design-contracts/avatar-fallback';
|
|
4
|
+
/** Optional animated entry. Static avatar imports never load motion CSS. */
|
|
5
|
+
export declare function createAnimatedBlobatarFallback(options: BlobatarMotionOptions): (context: AvatarFallbackContext) => ReactNode;
|
|
6
|
+
//# sourceMappingURL=avatar-blobatar-motion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"avatar-blobatar-motion.d.ts","sourceRoot":"","sources":["../src/avatar-blobatar-motion.tsx"],"names":[],"mappings":"AAAA,OAAM,EAA2B,KAAK,SAAS,EAAC,MAAI,OAAO,CAAC;AAAqH,OAAM,qBAAqB,CAAC;AAC7M,OAAM,EAAuB,KAAK,qBAAqB,EAAC,KAAK,qBAAqB,EAAC,MAAI,yCAAyC,CAAC;AAOjI,4EAA4E;AAC5E,wBAAgB,8BAA8B,CAAC,OAAO,EAAC,qBAAqB,GAAE,CAAC,OAAO,EAAC,qBAAqB,KAAG,SAAS,CAA0F"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { Blobatar } from '@blobatar/react';
|
|
4
|
+
import { idle, happy, sad, surprised, wink, sleepy, thinking } from 'blobatar/expression';
|
|
5
|
+
import 'blobatar/motion.css';
|
|
6
|
+
import { resolveBlobatarMotion } from '@hjmds/design-contracts/avatar-fallback';
|
|
7
|
+
import { useHjmTheme } from './provider.js';
|
|
8
|
+
const expressions = { idle, happy, sad, surprised, wink, sleepy, thinking };
|
|
9
|
+
function Artwork({ size, options }) {
|
|
10
|
+
const spec = resolveBlobatarMotion(options);
|
|
11
|
+
const { environment } = useHjmTheme();
|
|
12
|
+
const host = useRef(null);
|
|
13
|
+
const [visible, setVisible] = useState(false);
|
|
14
|
+
const [foreground, setForeground] = useState(false);
|
|
15
|
+
useEffect(() => { const update = () => setForeground(!document.hidden); update(); document.addEventListener('visibilitychange', update); const observer = new IntersectionObserver(entries => setVisible(entries.some(e => e.isIntersecting))); if (host.current)
|
|
16
|
+
observer.observe(host.current); return () => { observer.disconnect(); document.removeEventListener('visibilitychange', update); }; }, []);
|
|
17
|
+
const active = spec.active && spec.visible && visible && foreground && !environment.reducedMotion;
|
|
18
|
+
return _jsx("span", { ref: host, "aria-hidden": "true", style: { display: 'block' }, children: _jsx(Blobatar, { name: spec.seed, size: size, normalize: false, expression: expressions[spec.expression], animate: active ? 'always' : false, alt: "", "aria-hidden": "true" }) });
|
|
19
|
+
}
|
|
20
|
+
/** Optional animated entry. Static avatar imports never load motion CSS. */
|
|
21
|
+
export function createAnimatedBlobatarFallback(options) { resolveBlobatarMotion(options); return ({ size }) => _jsx(Artwork, { size: size, options: options }); }
|
|
22
|
+
//# sourceMappingURL=avatar-blobatar-motion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"avatar-blobatar-motion.js","sourceRoot":"","sources":["../src/avatar-blobatar-motion.tsx"],"names":[],"mappings":";AAAA,OAAM,EAAC,SAAS,EAAC,MAAM,EAAC,QAAQ,EAAgB,MAAI,OAAO,CAAC;AAAA,OAAM,EAAC,QAAQ,EAAC,MAAI,iBAAiB,CAAC;AAAA,OAAM,EAAC,IAAI,EAAC,KAAK,EAAC,GAAG,EAAC,SAAS,EAAC,IAAI,EAAC,MAAM,EAAC,QAAQ,EAAC,MAAI,qBAAqB,CAAC;AAAA,OAAM,qBAAqB,CAAC;AAC7M,OAAM,EAAC,qBAAqB,EAAuD,MAAI,yCAAyC,CAAC;AAAA,OAAM,EAAC,WAAW,EAAC,MAAI,eAAe,CAAC;AACxK,MAAM,WAAW,GAAC,EAAC,IAAI,EAAC,KAAK,EAAC,GAAG,EAAC,SAAS,EAAC,IAAI,EAAC,MAAM,EAAC,QAAQ,EAAC,CAAC;AAClE,SAAS,OAAO,CAAC,EAAC,IAAI,EAAC,OAAO,EAA6C;IAAE,MAAM,IAAI,GAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAAA,MAAK,EAAC,WAAW,EAAC,GAAC,WAAW,EAAE,CAAC;IAAA,MAAM,IAAI,GAAC,MAAM,CAAkB,IAAI,CAAC,CAAC;IAAA,MAAK,CAAC,OAAO,EAAC,UAAU,CAAC,GAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAAA,MAAK,CAAC,UAAU,EAAC,aAAa,CAAC,GAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1R,SAAS,CAAC,GAAE,EAAE,GAAC,MAAM,MAAM,GAAC,GAAE,EAAE,CAAA,aAAa,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAA,MAAM,EAAE,CAAC,CAAA,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAC,MAAM,CAAC,CAAC,CAAA,MAAM,QAAQ,GAAC,IAAI,oBAAoB,CAAC,OAAO,CAAA,EAAE,CAAA,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA,EAAE,CAAA,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAA,IAAG,IAAI,CAAC,OAAO;QAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA,OAAM,GAAE,EAAE,GAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA,QAAQ,CAAC,mBAAmB,CAAC,kBAAkB,EAAC,MAAM,CAAC,CAAC,CAAA,CAAC,CAAC,CAAA,CAAC,EAAC,EAAE,CAAC,CAAC;IAC9W,MAAM,MAAM,GAAC,IAAI,CAAC,MAAM,IAAE,IAAI,CAAC,OAAO,IAAE,OAAO,IAAE,UAAU,IAAE,CAAC,WAAW,CAAC,aAAa,CAAC;IACxF,OAAO,eAAM,GAAG,EAAE,IAAI,iBAAc,MAAM,EAAC,KAAK,EAAE,EAAC,OAAO,EAAC,OAAO,EAAC,YAAE,KAAC,QAAQ,IAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,MAAM,CAAA,CAAC,CAAA,QAAQ,CAAA,CAAC,CAAA,KAAK,EAAE,GAAG,EAAC,EAAE,iBAAa,MAAM,GAAE,GAAO,CAAC;AAC5O,CAAC;AACD,4EAA4E;AAC5E,MAAM,UAAU,8BAA8B,CAAC,OAA6B,IAA6C,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAA,OAAM,CAAC,EAAC,IAAI,EAAC,EAAC,EAAE,CAAA,KAAC,OAAO,IAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,CAAA,CAAC","sourcesContent":["import{useEffect,useRef,useState,type ReactNode}from'react';import{Blobatar}from'@blobatar/react';import{idle,happy,sad,surprised,wink,sleepy,thinking}from'blobatar/expression';import'blobatar/motion.css';\nimport{resolveBlobatarMotion,type BlobatarMotionOptions,type AvatarFallbackContext}from'@hjmds/design-contracts/avatar-fallback';import{useHjmTheme}from'./provider.js';\nconst expressions={idle,happy,sad,surprised,wink,sleepy,thinking};\nfunction Artwork({size,options}:{size:number;options:BlobatarMotionOptions}){const spec=resolveBlobatarMotion(options);const{environment}=useHjmTheme();const host=useRef<HTMLSpanElement>(null);const[visible,setVisible]=useState(false);const[foreground,setForeground]=useState(false);\n useEffect(()=>{const update=()=>setForeground(!document.hidden);update();document.addEventListener('visibilitychange',update);const observer=new IntersectionObserver(entries=>setVisible(entries.some(e=>e.isIntersecting)));if(host.current)observer.observe(host.current);return()=>{observer.disconnect();document.removeEventListener('visibilitychange',update);};},[]);\n const active=spec.active&&spec.visible&&visible&&foreground&&!environment.reducedMotion;\n return <span ref={host} aria-hidden=\"true\" style={{display:'block'}}><Blobatar name={spec.seed} size={size} normalize={false} expression={expressions[spec.expression]} animate={active?'always':false} alt=\"\" aria-hidden=\"true\"/></span>;\n}\n/** Optional animated entry. Static avatar imports never load motion CSS. */\nexport function createAnimatedBlobatarFallback(options:BlobatarMotionOptions):(context:AvatarFallbackContext)=>ReactNode{resolveBlobatarMotion(options);return({size})=><Artwork size={size} options={options}/>;}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type AvatarFallbackContext, type BlobatarFallbackOptions } from "@hjmds/design-contracts/avatar-fallback";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
export type { BlobatarFallbackOptions } from "@hjmds/design-contracts/avatar-fallback";
|
|
4
|
+
/** Optional, local artwork. Avatar owns naming and image-error recovery. */
|
|
5
|
+
export declare function createBlobatarFallback(options: BlobatarFallbackOptions): (context: AvatarFallbackContext) => ReactNode;
|
|
6
|
+
//# sourceMappingURL=avatar-blobatar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"avatar-blobatar.d.ts","sourceRoot":"","sources":["../src/avatar-blobatar.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA2B,KAAK,qBAAqB,EAAE,KAAK,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAC5I,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,YAAY,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AACvF,4EAA4E;AAC5E,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,GAAG,CAAC,OAAO,EAAE,qBAAqB,KAAK,SAAS,CAKtH"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Blobatar } from "@blobatar/react";
|
|
3
|
+
import { happy } from "blobatar/expression";
|
|
4
|
+
import { resolveBlobatarFallback } from "@hjmds/design-contracts/avatar-fallback";
|
|
5
|
+
/** Optional, local artwork. Avatar owns naming and image-error recovery. */
|
|
6
|
+
export function createBlobatarFallback(options) {
|
|
7
|
+
const { seed, expression } = resolveBlobatarFallback(options);
|
|
8
|
+
return ({ size }) => _jsx(Blobatar, { name: seed, size: size, normalize: false, animate: false, ...(expression === "happy" ? { expression: happy } : {}), alt: "", "aria-hidden": "true", style: { display: "block" } });
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=avatar-blobatar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"avatar-blobatar.js","sourceRoot":"","sources":["../src/avatar-blobatar.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,uBAAuB,EAA4D,MAAM,yCAAyC,CAAC;AAG5I,4EAA4E;AAC5E,MAAM,UAAU,sBAAsB,CAAC,OAAgC;IACrE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,uBAAuB,CAAC,OAAO,CAAC,CAAC;IAC9D,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,KAAC,QAAQ,IAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,KACjF,CAAC,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EACzD,GAAG,EAAC,EAAE,iBAAa,MAAM,EAAC,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,GAAI,CAAC;AAC9D,CAAC","sourcesContent":["import { Blobatar } from \"@blobatar/react\";\nimport { happy } from \"blobatar/expression\";\nimport { resolveBlobatarFallback, type AvatarFallbackContext, type BlobatarFallbackOptions } from \"@hjmds/design-contracts/avatar-fallback\";\nimport type { ReactNode } from \"react\";\nexport type { BlobatarFallbackOptions } from \"@hjmds/design-contracts/avatar-fallback\";\n/** Optional, local artwork. Avatar owns naming and image-error recovery. */\nexport function createBlobatarFallback(options: BlobatarFallbackOptions): (context: AvatarFallbackContext) => ReactNode {\n const { seed, expression } = resolveBlobatarFallback(options);\n return ({ size }) => <Blobatar name={seed} size={size} normalize={false} animate={false}\n {...(expression === \"happy\" ? { expression: happy } : {})}\n alt=\"\" aria-hidden=\"true\" style={{ display: \"block\" }} />;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bottom-navigation.d.ts","sourceRoot":"","sources":["../src/bottom-navigation.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,0BAA0B,EAC/B,KAAK,6BAA6B,EAClC,KAAK,0BAA0B,EAC/B,KAAK,sCAAsC,EAC5C,MAAM,sDAAsD,CAAC;AAK9D,OAAO,EAIL,KAAK,oBAAoB,EAGzB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,aAAa,EACnB,MAAM,OAAO,CAAC;AAMf,MAAM,MAAM,+BAA+B,CACzC,GAAG,SAAS,MAAM,GAAG,MAAM,EAC3B,QAAQ,SAAS,MAAM,GAAG,MAAM,IAC9B,QAAQ,CAAC;IACX,IAAI,EAAE,sCAAsC,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC5D,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,cAAc,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAEH,MAAM,MAAM,+BAA+B,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,GACnF,QAAQ,CAAC;IACP,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,UAAU,CAAC;CACnC,CAAC,CAAC;AAEL,MAAM,MAAM,qBAAqB,CAC/B,GAAG,SAAS,MAAM,GAAG,MAAM,EAC3B,QAAQ,SAAS,MAAM,GAAG,MAAM,IAC9B,IAAI,CACN,cAAc,CAAC,WAAW,CAAC,EAC3B,YAAY,GAAG,iBAAiB,GAAG,UAAU,GAAG,KAAK,GAAG,UAAU,GAAG,MAAM,CAC5E,GACC,QAAQ,CAAC;IACP,UAAU,EAAE,0BAA0B,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACtD,aAAa,CAAC,EAAE,6BAA6B,CAAC;IAC9C,OAAO,EAAE,CAAC,IAAI,EAAE,sCAAsC,CAAC,GAAG,EAAE,QAAQ,CAAC,KAAK,MAAM,CAAC;IACjF,UAAU,EAAE,CAAC,KAAK,EAAE,+BAA+B,CAAC,GAAG,EAAE,QAAQ,CAAC,KAAK,SAAS,CAAC;IACjF,8DAA8D;IAC9D,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,+BAA+B,KAAK,YAAY,CAAC;IACtE,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,0BAA0B,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;CACpE,CAAC,CAAC;AAEL,wBAAgB,wCAAwC,CACtD,KAAK,EAAE,IAAI,CACT,UAAU,CAAC,iBAAiB,CAAC,EAC7B,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,kBAAkB,GAAG,SAAS,GAAG,UAAU,CAC9E,GACA,OAAO,CAST;AAED,wBAAgB,qCAAqC,CAAC,KAAK,EAAE,QAAQ,CAAC;IACpE,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC5B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC,GAAG,OAAO,CAOX;AAMD,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,OAAO,GAAG,YAAY,GACnC,MAAM,GAAG,SAAS,CAIpB;
|
|
1
|
+
{"version":3,"file":"bottom-navigation.d.ts","sourceRoot":"","sources":["../src/bottom-navigation.tsx"],"names":[],"mappings":"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"}
|
|
@@ -71,7 +71,7 @@ function BottomNavigationInner({ descriptor, configuration = {}, getHref, render
|
|
|
71
71
|
const iconSize = iconRecipe.sizes[density.icon];
|
|
72
72
|
if (hidden)
|
|
73
73
|
return null;
|
|
74
|
-
return (_jsx("nav", { ...props, ref: ref, "aria-label": resolved.accessibilityLabel, className: classNames("hjm-bottom-navigation", className), "data-density": presentation.density, "data-distribution": presentation.distribution, "data-keyboard-behavior": presentation.keyboardBehavior, "data-presentation": presentation.presentation, dir: presentation.direction, style: {
|
|
74
|
+
return (_jsx("nav", { ...props, ref: ref, "aria-label": resolved.accessibilityLabel, className: classNames("hjm-bottom-navigation", className), "data-expanded-labels": (theme?.environment.textScale ?? 1) >= 1.5 || resolved.items.length > 4 ? "true" : "false", "data-density": presentation.density, "data-distribution": presentation.distribution, "data-keyboard-behavior": presentation.keyboardBehavior, "data-presentation": presentation.presentation, dir: presentation.direction, style: {
|
|
75
75
|
"--hjm-bottom-navigation-center-gap": `${centerGap}px`,
|
|
76
76
|
"--hjm-bottom-navigation-columns": resolved.items.length,
|
|
77
77
|
"--hjm-bottom-navigation-half-columns": resolved.items.length / 2,
|
|
@@ -104,7 +104,7 @@ function BottomNavigationInner({ descriptor, configuration = {}, getHref, render
|
|
|
104
104
|
gridColumn: getBottomNavigationGridColumn(index, resolved.items.length, presentation.distribution),
|
|
105
105
|
};
|
|
106
106
|
if (item.disabled) {
|
|
107
|
-
return (_jsx("li", { style: itemStyle, children: _jsx("span", { "aria-disabled": "true", "aria-label": item.resolvedAccessibilityLabel, className: "hjm-bottom-navigation__item", "data-state": "disabled", role: "link", children: content }) }, item.id));
|
|
107
|
+
return (_jsx("li", { style: itemStyle, "data-selected": "false", children: _jsx("span", { "aria-disabled": "true", "aria-label": item.resolvedAccessibilityLabel, className: "hjm-bottom-navigation__item", "data-state": "disabled", role: "link", children: content }) }, item.id));
|
|
108
108
|
}
|
|
109
109
|
const href = getHref(item);
|
|
110
110
|
if (!href.trim()) {
|
|
@@ -125,7 +125,7 @@ function BottomNavigationInner({ descriptor, configuration = {}, getHref, render
|
|
|
125
125
|
},
|
|
126
126
|
children: content,
|
|
127
127
|
};
|
|
128
|
-
return (_jsx("li", { style: itemStyle, children: renderLink ? renderLink(linkProps) : _jsx("a", { ...linkProps }) }, item.id));
|
|
128
|
+
return (_jsx("li", { style: itemStyle, "data-selected": selected, children: renderLink ? renderLink(linkProps) : _jsx("a", { ...linkProps }) }, item.id));
|
|
129
129
|
}) }), primaryAction ? (_jsx("div", { className: "hjm-bottom-navigation__primary-action", children: primaryAction })) : null] }) }));
|
|
130
130
|
}
|
|
131
131
|
export const BottomNavigation = forwardRef(BottomNavigationInner);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bottom-navigation.js","sourceRoot":"","sources":["../src/bottom-navigation.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n resolveBottomNavigationActivation,\n resolveBottomNavigationConfiguration,\n resolveBottomNavigationDescriptor,\n type BottomNavigationActivation,\n type BottomNavigationConfiguration,\n type BottomNavigationDescriptor,\n type ResolvedBottomNavigationItemDescriptor,\n} from \"@hjmds/design-contracts/components/bottom-navigation\";\nimport {\n bottomNavigationRecipe,\n iconRecipe,\n} from \"@hjmds/design-contracts/recipes\";\nimport {\n forwardRef,\n useEffect,\n useState,\n type AnchorHTMLAttributes,\n type CSSProperties,\n type ForwardedRef,\n type HTMLAttributes,\n type MouseEvent,\n type ReactElement,\n type ReactNode,\n type RefAttributes,\n} from \"react\";\nimport { classNames } from \"./internal.js\";\nimport { useOptionalHjmTheme } from \"./provider.js\";\n\nconst virtualKeyboardMinimumOcclusion = 120;\n\nexport type BottomNavigationIconRenderProps<\n Key extends string = string,\n IconName extends string = string,\n> = Readonly<{\n item: ResolvedBottomNavigationItemDescriptor<Key, IconName>;\n name: IconName;\n selected: boolean;\n color: \"currentColor\";\n size: number;\n strokeWidth: number;\n scale: number;\n}>;\n\nexport type BottomNavigationLinkRenderProps = AnchorHTMLAttributes<HTMLAnchorElement> &\n Readonly<{\n href: string;\n children: ReactNode;\n \"data-state\": \"idle\" | \"selected\";\n }>;\n\nexport type BottomNavigationProps<\n Key extends string = string,\n IconName extends string = string,\n> = Omit<\n HTMLAttributes<HTMLElement>,\n \"aria-label\" | \"aria-labelledby\" | \"children\" | \"dir\" | \"onChange\" | \"role\"\n> &\n Readonly<{\n descriptor: BottomNavigationDescriptor<Key, IconName>;\n configuration?: BottomNavigationConfiguration;\n getHref: (item: ResolvedBottomNavigationItemDescriptor<Key, IconName>) => string;\n renderIcon: (props: BottomNavigationIconRenderProps<Key, IconName>) => ReactNode;\n /** Framework navigation adapter, for example Next.js Link. */\n renderLink?: (props: BottomNavigationLinkRenderProps) => ReactElement;\n primaryAction?: ReactNode;\n onActivate?: (activation: BottomNavigationActivation<Key>) => void;\n }>;\n\nexport function isUnmodifiedPrimaryBottomNavigationClick(\n event: Pick<\n MouseEvent<HTMLAnchorElement>,\n \"altKey\" | \"button\" | \"ctrlKey\" | \"defaultPrevented\" | \"metaKey\" | \"shiftKey\"\n >,\n): boolean {\n return (\n !event.defaultPrevented &&\n event.button === 0 &&\n !event.metaKey &&\n !event.ctrlKey &&\n !event.shiftKey &&\n !event.altKey\n );\n}\n\nexport function shouldHideBottomNavigationForKeyboard(input: Readonly<{\n behavior: \"hide\" | \"remain\";\n layoutViewportHeight: number;\n visualViewportHeight: number;\n visualViewportOffsetTop?: number;\n visualViewportScale?: number;\n}>): boolean {\n if (input.behavior !== \"hide\") return false;\n if ((input.visualViewportScale ?? 1) !== 1) return false;\n const visibleBottom =\n input.visualViewportHeight + (input.visualViewportOffsetTop ?? 0);\n return layoutViewportHeightIsValid(input.layoutViewportHeight) &&\n input.layoutViewportHeight - visibleBottom >= virtualKeyboardMinimumOcclusion;\n}\n\nfunction layoutViewportHeightIsValid(value: number): boolean {\n return Number.isFinite(value) && value >= 0;\n}\n\nexport function getBottomNavigationGridColumn(\n index: number,\n itemCount: number,\n distribution: \"equal\" | \"center-gap\",\n): number | undefined {\n if (distribution !== \"center-gap\") return undefined;\n const middle = itemCount / 2;\n return index < middle ? index + 1 : index + 2;\n}\n\nfunction useKeyboardHidden(behavior: \"hide\" | \"remain\"): boolean {\n const [hidden, setHidden] = useState(false);\n useEffect(() => {\n const viewport = window.visualViewport;\n if (!viewport) return;\n const update = () => {\n setHidden(\n shouldHideBottomNavigationForKeyboard({\n behavior,\n layoutViewportHeight: window.innerHeight,\n visualViewportHeight: viewport.height,\n visualViewportOffsetTop: viewport.offsetTop,\n visualViewportScale: viewport.scale,\n }),\n );\n };\n update();\n viewport.addEventListener(\"resize\", update);\n viewport.addEventListener(\"scroll\", update);\n return () => {\n viewport.removeEventListener(\"resize\", update);\n viewport.removeEventListener(\"scroll\", update);\n };\n }, [behavior]);\n return hidden;\n}\n\nfunction BottomNavigationInner<\n Key extends string = string,\n IconName extends string = string,\n>(\n {\n descriptor,\n configuration = {},\n getHref,\n renderIcon,\n renderLink,\n primaryAction,\n onActivate,\n className,\n style,\n ...props\n }: BottomNavigationProps<Key, IconName>,\n ref: ForwardedRef<HTMLElement>,\n) {\n const resolved = resolveBottomNavigationDescriptor(descriptor);\n const theme = useOptionalHjmTheme();\n const direction = configuration.direction ?? theme?.environment.direction;\n const presentation = resolveBottomNavigationConfiguration(\n {\n ...configuration,\n ...(direction === undefined ? {} : { direction }),\n },\n resolved.items.length,\n );\n const hidden = useKeyboardHidden(presentation.keyboardBehavior);\n const density = bottomNavigationRecipe.density[presentation.density];\n const presentationRecipe =\n bottomNavigationRecipe.presentations[presentation.presentation];\n const centerGap =\n bottomNavigationRecipe.distributions[presentation.distribution].centerGap;\n const iconSize = iconRecipe.sizes[density.icon];\n\n if (hidden) return null;\n\n return (\n <nav\n {...props}\n ref={ref}\n aria-label={resolved.accessibilityLabel}\n className={classNames(\"hjm-bottom-navigation\", className)}\n data-density={presentation.density}\n data-distribution={presentation.distribution}\n data-keyboard-behavior={presentation.keyboardBehavior}\n data-presentation={presentation.presentation}\n dir={presentation.direction}\n style={{\n \"--hjm-bottom-navigation-center-gap\": `${centerGap}px`,\n \"--hjm-bottom-navigation-columns\": resolved.items.length,\n \"--hjm-bottom-navigation-half-columns\": resolved.items.length / 2,\n \"--hjm-bottom-navigation-item-gap\": `${density.gap}px`,\n \"--hjm-bottom-navigation-item-min-height\": `${density.itemMinHeight}px`,\n \"--hjm-bottom-navigation-item-min-width\": `${density.itemMinWidth}px`,\n \"--hjm-bottom-navigation-item-padding\": `${density.padding}px`,\n \"--hjm-bottom-navigation-max-width\": presentationRecipe.maxWidth\n ? `${presentationRecipe.maxWidth}px`\n : \"none\",\n \"--hjm-bottom-navigation-outer-inline\": `${presentationRecipe.outerPaddingHorizontal}px`,\n \"--hjm-bottom-navigation-outer-top\": `${presentationRecipe.outerPaddingTop}px`,\n ...style,\n } as CSSProperties}\n >\n <div className=\"hjm-bottom-navigation__surface\">\n <ul className=\"hjm-bottom-navigation__list\">\n {resolved.items.map((item, index) => {\n const selected = item.id === resolved.selectedKey;\n const content = (\n <>\n <span\n aria-hidden=\"true\"\n className=\"hjm-bottom-navigation__indicator\"\n data-state={selected ? \"selected\" : \"idle\"}\n >\n {renderIcon({\n item,\n name: item.icon.name,\n selected,\n color: \"currentColor\",\n size: iconSize,\n strokeWidth: selected\n ? bottomNavigationRecipe.icon.selectedEmphasis.strokeWidth.selected\n : bottomNavigationRecipe.icon.selectedEmphasis.strokeWidth.idle,\n scale: selected\n ? bottomNavigationRecipe.icon.selectedEmphasis.scale.selected\n : bottomNavigationRecipe.icon.selectedEmphasis.scale.idle,\n })}\n {item.badge ? (\n <span aria-hidden=\"true\" className=\"hjm-bottom-navigation__badge\">\n {item.badge.visibleLabel}\n </span>\n ) : null}\n </span>\n <span className=\"hjm-bottom-navigation__label\">{item.label}</span>\n </>\n );\n const itemStyle = {\n gridColumn: getBottomNavigationGridColumn(\n index,\n resolved.items.length,\n presentation.distribution,\n ),\n };\n if (item.disabled) {\n return (\n <li key={item.id} style={itemStyle}>\n <span\n aria-disabled=\"true\"\n aria-label={item.resolvedAccessibilityLabel}\n className=\"hjm-bottom-navigation__item\"\n data-state=\"disabled\"\n role=\"link\"\n >\n {content}\n </span>\n </li>\n );\n }\n const href = getHref(item);\n if (!href.trim()) {\n throw new TypeError(`BottomNavigation href must not be empty: ${item.id}`);\n }\n const linkProps: BottomNavigationLinkRenderProps = {\n \"aria-current\": selected ? \"page\" : undefined,\n \"aria-label\": item.resolvedAccessibilityLabel,\n className: \"hjm-bottom-navigation__item\",\n \"data-state\": selected ? \"selected\" : \"idle\",\n href,\n onClick: (event) => {\n if (!isUnmodifiedPrimaryBottomNavigationClick(event)) return;\n const activation = resolveBottomNavigationActivation(descriptor, item.id);\n if (activation) onActivate?.(activation);\n },\n children: content,\n };\n return (\n <li key={item.id} style={itemStyle}>\n {renderLink ? renderLink(linkProps) : <a {...linkProps} />}\n </li>\n );\n })}\n </ul>\n {primaryAction ? (\n <div className=\"hjm-bottom-navigation__primary-action\">{primaryAction}</div>\n ) : null}\n </div>\n </nav>\n );\n}\n\nexport const BottomNavigation = forwardRef(BottomNavigationInner) as <\n Key extends string = string,\n IconName extends string = string,\n>(\n props: BottomNavigationProps<Key, IconName> & RefAttributes<HTMLElement>,\n) => ReactElement | null;\n"]}
|
|
1
|
+
{"version":3,"file":"bottom-navigation.js","sourceRoot":"","sources":["../src/bottom-navigation.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n resolveBottomNavigationActivation,\n resolveBottomNavigationConfiguration,\n resolveBottomNavigationDescriptor,\n type BottomNavigationActivation,\n type BottomNavigationConfiguration,\n type BottomNavigationDescriptor,\n type ResolvedBottomNavigationItemDescriptor,\n} from \"@hjmds/design-contracts/components/bottom-navigation\";\nimport {\n bottomNavigationRecipe,\n iconRecipe,\n} from \"@hjmds/design-contracts/recipes\";\nimport {\n forwardRef,\n useEffect,\n useState,\n type AnchorHTMLAttributes,\n type CSSProperties,\n type ForwardedRef,\n type HTMLAttributes,\n type MouseEvent,\n type ReactElement,\n type ReactNode,\n type RefAttributes,\n} from \"react\";\nimport { classNames } from \"./internal.js\";\nimport { useOptionalHjmTheme } from \"./provider.js\";\n\nconst virtualKeyboardMinimumOcclusion = 120;\n\nexport type BottomNavigationIconRenderProps<\n Key extends string = string,\n IconName extends string = string,\n> = Readonly<{\n item: ResolvedBottomNavigationItemDescriptor<Key, IconName>;\n name: IconName;\n selected: boolean;\n color: \"currentColor\";\n size: number;\n strokeWidth: number;\n scale: number;\n}>;\n\nexport type BottomNavigationLinkRenderProps = AnchorHTMLAttributes<HTMLAnchorElement> &\n Readonly<{\n href: string;\n children: ReactNode;\n \"data-state\": \"idle\" | \"selected\";\n }>;\n\nexport type BottomNavigationProps<\n Key extends string = string,\n IconName extends string = string,\n> = Omit<\n HTMLAttributes<HTMLElement>,\n \"aria-label\" | \"aria-labelledby\" | \"children\" | \"dir\" | \"onChange\" | \"role\"\n> &\n Readonly<{\n descriptor: BottomNavigationDescriptor<Key, IconName>;\n configuration?: BottomNavigationConfiguration;\n getHref: (item: ResolvedBottomNavigationItemDescriptor<Key, IconName>) => string;\n renderIcon: (props: BottomNavigationIconRenderProps<Key, IconName>) => ReactNode;\n /** Framework navigation adapter, for example Next.js Link. */\n renderLink?: (props: BottomNavigationLinkRenderProps) => ReactElement;\n primaryAction?: ReactNode;\n onActivate?: (activation: BottomNavigationActivation<Key>) => void;\n }>;\n\nexport function isUnmodifiedPrimaryBottomNavigationClick(\n event: Pick<\n MouseEvent<HTMLAnchorElement>,\n \"altKey\" | \"button\" | \"ctrlKey\" | \"defaultPrevented\" | \"metaKey\" | \"shiftKey\"\n >,\n): boolean {\n return (\n !event.defaultPrevented &&\n event.button === 0 &&\n !event.metaKey &&\n !event.ctrlKey &&\n !event.shiftKey &&\n !event.altKey\n );\n}\n\nexport function shouldHideBottomNavigationForKeyboard(input: Readonly<{\n behavior: \"hide\" | \"remain\";\n layoutViewportHeight: number;\n visualViewportHeight: number;\n visualViewportOffsetTop?: number;\n visualViewportScale?: number;\n}>): boolean {\n if (input.behavior !== \"hide\") return false;\n if ((input.visualViewportScale ?? 1) !== 1) return false;\n const visibleBottom =\n input.visualViewportHeight + (input.visualViewportOffsetTop ?? 0);\n return layoutViewportHeightIsValid(input.layoutViewportHeight) &&\n input.layoutViewportHeight - visibleBottom >= virtualKeyboardMinimumOcclusion;\n}\n\nfunction layoutViewportHeightIsValid(value: number): boolean {\n return Number.isFinite(value) && value >= 0;\n}\n\nexport function getBottomNavigationGridColumn(\n index: number,\n itemCount: number,\n distribution: \"equal\" | \"center-gap\",\n): number | undefined {\n if (distribution !== \"center-gap\") return undefined;\n const middle = itemCount / 2;\n return index < middle ? index + 1 : index + 2;\n}\n\nfunction useKeyboardHidden(behavior: \"hide\" | \"remain\"): boolean {\n const [hidden, setHidden] = useState(false);\n useEffect(() => {\n const viewport = window.visualViewport;\n if (!viewport) return;\n const update = () => {\n setHidden(\n shouldHideBottomNavigationForKeyboard({\n behavior,\n layoutViewportHeight: window.innerHeight,\n visualViewportHeight: viewport.height,\n visualViewportOffsetTop: viewport.offsetTop,\n visualViewportScale: viewport.scale,\n }),\n );\n };\n update();\n viewport.addEventListener(\"resize\", update);\n viewport.addEventListener(\"scroll\", update);\n return () => {\n viewport.removeEventListener(\"resize\", update);\n viewport.removeEventListener(\"scroll\", update);\n };\n }, [behavior]);\n return hidden;\n}\n\nfunction BottomNavigationInner<\n Key extends string = string,\n IconName extends string = string,\n>(\n {\n descriptor,\n configuration = {},\n getHref,\n renderIcon,\n renderLink,\n primaryAction,\n onActivate,\n className,\n style,\n ...props\n }: BottomNavigationProps<Key, IconName>,\n ref: ForwardedRef<HTMLElement>,\n) {\n const resolved = resolveBottomNavigationDescriptor(descriptor);\n const theme = useOptionalHjmTheme();\n const direction = configuration.direction ?? theme?.environment.direction;\n const presentation = resolveBottomNavigationConfiguration(\n {\n ...configuration,\n ...(direction === undefined ? {} : { direction }),\n },\n resolved.items.length,\n );\n const hidden = useKeyboardHidden(presentation.keyboardBehavior);\n const density = bottomNavigationRecipe.density[presentation.density];\n const presentationRecipe =\n bottomNavigationRecipe.presentations[presentation.presentation];\n const centerGap =\n bottomNavigationRecipe.distributions[presentation.distribution].centerGap;\n const iconSize = iconRecipe.sizes[density.icon];\n\n if (hidden) return null;\n\n return (\n <nav\n {...props}\n ref={ref}\n aria-label={resolved.accessibilityLabel}\n className={classNames(\"hjm-bottom-navigation\", className)}\n data-expanded-labels={(theme?.environment.textScale ?? 1) >= 1.5 || resolved.items.length > 4 ? \"true\" : \"false\"}\n data-density={presentation.density}\n data-distribution={presentation.distribution}\n data-keyboard-behavior={presentation.keyboardBehavior}\n data-presentation={presentation.presentation}\n dir={presentation.direction}\n style={{\n \"--hjm-bottom-navigation-center-gap\": `${centerGap}px`,\n \"--hjm-bottom-navigation-columns\": resolved.items.length,\n \"--hjm-bottom-navigation-half-columns\": resolved.items.length / 2,\n \"--hjm-bottom-navigation-item-gap\": `${density.gap}px`,\n \"--hjm-bottom-navigation-item-min-height\": `${density.itemMinHeight}px`,\n \"--hjm-bottom-navigation-item-min-width\": `${density.itemMinWidth}px`,\n \"--hjm-bottom-navigation-item-padding\": `${density.padding}px`,\n \"--hjm-bottom-navigation-max-width\": presentationRecipe.maxWidth\n ? `${presentationRecipe.maxWidth}px`\n : \"none\",\n \"--hjm-bottom-navigation-outer-inline\": `${presentationRecipe.outerPaddingHorizontal}px`,\n \"--hjm-bottom-navigation-outer-top\": `${presentationRecipe.outerPaddingTop}px`,\n ...style,\n } as CSSProperties}\n >\n <div className=\"hjm-bottom-navigation__surface\">\n <ul className=\"hjm-bottom-navigation__list\">\n {resolved.items.map((item, index) => {\n const selected = item.id === resolved.selectedKey;\n const content = (\n <>\n <span\n aria-hidden=\"true\"\n className=\"hjm-bottom-navigation__indicator\"\n data-state={selected ? \"selected\" : \"idle\"}\n >\n {renderIcon({\n item,\n name: item.icon.name,\n selected,\n color: \"currentColor\",\n size: iconSize,\n strokeWidth: selected\n ? bottomNavigationRecipe.icon.selectedEmphasis.strokeWidth.selected\n : bottomNavigationRecipe.icon.selectedEmphasis.strokeWidth.idle,\n scale: selected\n ? bottomNavigationRecipe.icon.selectedEmphasis.scale.selected\n : bottomNavigationRecipe.icon.selectedEmphasis.scale.idle,\n })}\n {item.badge ? (\n <span aria-hidden=\"true\" className=\"hjm-bottom-navigation__badge\">\n {item.badge.visibleLabel}\n </span>\n ) : null}\n </span>\n <span className=\"hjm-bottom-navigation__label\">{item.label}</span>\n </>\n );\n const itemStyle = {\n gridColumn: getBottomNavigationGridColumn(\n index,\n resolved.items.length,\n presentation.distribution,\n ),\n };\n if (item.disabled) {\n return (\n <li key={item.id} style={itemStyle} data-selected=\"false\">\n <span\n aria-disabled=\"true\"\n aria-label={item.resolvedAccessibilityLabel}\n className=\"hjm-bottom-navigation__item\"\n data-state=\"disabled\"\n role=\"link\"\n >\n {content}\n </span>\n </li>\n );\n }\n const href = getHref(item);\n if (!href.trim()) {\n throw new TypeError(`BottomNavigation href must not be empty: ${item.id}`);\n }\n const linkProps: BottomNavigationLinkRenderProps = {\n \"aria-current\": selected ? \"page\" : undefined,\n \"aria-label\": item.resolvedAccessibilityLabel,\n className: \"hjm-bottom-navigation__item\",\n \"data-state\": selected ? \"selected\" : \"idle\",\n href,\n onClick: (event) => {\n if (!isUnmodifiedPrimaryBottomNavigationClick(event)) return;\n const activation = resolveBottomNavigationActivation(descriptor, item.id);\n if (activation) onActivate?.(activation);\n },\n children: content,\n };\n return (\n <li key={item.id} style={itemStyle} data-selected={selected}>\n {renderLink ? renderLink(linkProps) : <a {...linkProps} />}\n </li>\n );\n })}\n </ul>\n {primaryAction ? (\n <div className=\"hjm-bottom-navigation__primary-action\">{primaryAction}</div>\n ) : null}\n </div>\n </nav>\n );\n}\n\nexport const BottomNavigation = forwardRef(BottomNavigationInner) as <\n Key extends string = string,\n IconName extends string = string,\n>(\n props: BottomNavigationProps<Key, IconName> & RefAttributes<HTMLElement>,\n) => ReactElement | null;\n"]}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import type { SortableItem } from "@hjmds/design-contracts/components/interaction-adapters";
|
|
3
|
+
import { type ComposeCarouselAccessibleName } from "@hjmds/design-contracts/components/carousel";
|
|
3
4
|
export type CarouselMotionProps = {
|
|
4
5
|
slides: readonly SortableItem[];
|
|
5
6
|
currentKey: string;
|
|
6
7
|
onCurrentKeyChange(key: string): void;
|
|
8
|
+
/** Optional localized position/name composer shared with the base Carousel. */
|
|
9
|
+
composeAccessibleName?: ComposeCarouselAccessibleName;
|
|
7
10
|
renderSlide(item: SortableItem): ReactNode;
|
|
8
11
|
label: string;
|
|
9
12
|
previousLabel: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"carousel-motion.d.ts","sourceRoot":"","sources":["../src/carousel-motion.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEpE,OAAO,
|
|
1
|
+
{"version":3,"file":"carousel-motion.d.ts","sourceRoot":"","sources":["../src/carousel-motion.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yDAAyD,CAAC;AAC5F,OAAO,EAA0D,KAAK,6BAA6B,EAAE,MAAM,6CAA6C,CAAC;AAIzJ,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3F,+EAA+E;IAC/E,qBAAqB,CAAC,EAAE,6BAA6B,CAAC;IACtD,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;CACrG,CAAC;AACF,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,+BAwCxD"}
|
package/dist/carousel-motion.js
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef, useState } from "react";
|
|
3
3
|
import useEmblaCarousel from "embla-carousel-react";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveCarouselDescriptor, getCarouselNavigationTarget } from "@hjmds/design-contracts/components/carousel";
|
|
5
5
|
import { Button } from "./actions.js";
|
|
6
6
|
import { useHjmTheme } from "./provider.js";
|
|
7
7
|
export function CarouselMotion(props) {
|
|
8
|
-
const
|
|
8
|
+
const descriptor = { slides: props.slides, currentKey: props.currentKey };
|
|
9
|
+
// Share finite keyed selection and names with Carousel; the optional peer owns
|
|
10
|
+
// only swipe/motion. No autoplay is implied by this controlled presentation.
|
|
11
|
+
const resolved = resolveCarouselDescriptor(descriptor, {
|
|
12
|
+
composeAccessibleName: props.composeAccessibleName ?? ((info) => info.label),
|
|
13
|
+
});
|
|
14
|
+
const index = resolved.findIndex(slide => slide.current);
|
|
15
|
+
if (![props.label, props.previousLabel, props.nextLabel].every(label => label.trim())) {
|
|
16
|
+
throw new TypeError("CarouselMotion labels must not be empty");
|
|
17
|
+
}
|
|
9
18
|
const { environment } = useHjmTheme();
|
|
10
19
|
// Embla deep-compares options and reInits on change; a live startIndex restarted the engine at the target on
|
|
11
20
|
// every selection, so navigation snapped instead of animating (2026-09-30 review). Only the first index seeds it.
|
|
@@ -30,6 +39,6 @@ export function CarouselMotion(props) {
|
|
|
30
39
|
return () => { api.off("select", select); };
|
|
31
40
|
}, [api]);
|
|
32
41
|
useEffect(() => { syncing.current = true; api?.scrollTo(index, environment.reducedMotion); syncing.current = false; }, [api, index, environment.reducedMotion]);
|
|
33
|
-
return _jsxs("section", { "aria-label": props.label, "aria-roledescription": "carousel", children: [_jsx("div", { ref: viewport, style: { overflow: "hidden" }, children: _jsx("div", { style: { display: "flex", touchAction: "pan-y pinch-zoom" }, children: props.slides.map((slide, i) => _jsx("div", { role: "group", "aria-roledescription": "slide", "aria-label":
|
|
42
|
+
return _jsxs("section", { "aria-label": props.label, "aria-roledescription": "carousel", children: [_jsx("div", { ref: viewport, style: { overflow: "hidden" }, children: _jsx("div", { style: { display: "flex", touchAction: "pan-y pinch-zoom" }, children: props.slides.map((slide, i) => _jsx("div", { role: "group", "aria-roledescription": "slide", "aria-label": resolved[i].accessibleName, "aria-hidden": resolved[i].inert, inert: resolved[i].inert, style: { flex: "0 0 100%", minWidth: 0 }, children: props.renderSlide(slide) }, slide.id)) }) }), _jsx(Button, { tone: "ghost", disabled: index === 0, onClick: () => props.onCurrentKeyChange(getCarouselNavigationTarget(descriptor, "previous")), children: props.previousLabel }), _jsx(Button, { tone: "ghost", disabled: index === props.slides.length - 1, onClick: () => props.onCurrentKeyChange(getCarouselNavigationTarget(descriptor, "next")), children: props.nextLabel })] });
|
|
34
43
|
}
|
|
35
44
|
//# sourceMappingURL=carousel-motion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"carousel-motion.js","sourceRoot":"","sources":["../src/carousel-motion.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AACpE,OAAO,gBAAgB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"carousel-motion.js","sourceRoot":"","sources":["../src/carousel-motion.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport useEmblaCarousel from \"embla-carousel-react\";\nimport type { SortableItem } from \"@hjmds/design-contracts/components/interaction-adapters\";\nimport { resolveCarouselDescriptor, getCarouselNavigationTarget, type ComposeCarouselAccessibleName } from \"@hjmds/design-contracts/components/carousel\";\nimport { Button } from \"./actions.js\";\nimport { useHjmTheme } from \"./provider.js\";\n\nexport type CarouselMotionProps = {\n slides: readonly SortableItem[]; currentKey: string; onCurrentKeyChange(key: string): void;\n /** Optional localized position/name composer shared with the base Carousel. */\n composeAccessibleName?: ComposeCarouselAccessibleName;\n renderSlide(item: SortableItem): ReactNode; label: string; previousLabel: string; nextLabel: string;\n};\nexport function CarouselMotion(props: CarouselMotionProps) {\n const descriptor = { slides: props.slides, currentKey: props.currentKey };\n // Share finite keyed selection and names with Carousel; the optional peer owns\n // only swipe/motion. No autoplay is implied by this controlled presentation.\n const resolved = resolveCarouselDescriptor(descriptor, {\n composeAccessibleName: props.composeAccessibleName ?? ((info) => info.label),\n });\n const index = resolved.findIndex(slide => slide.current);\n if (![props.label, props.previousLabel, props.nextLabel].every(label => label.trim())) {\n throw new TypeError(\"CarouselMotion labels must not be empty\");\n }\n const { environment } = useHjmTheme();\n // Embla deep-compares options and reInits on change; a live startIndex restarted the engine at the target on\n // every selection, so navigation snapped instead of animating (2026-09-30 review). Only the first index seeds it.\n const [startIndex] = useState(index);\n const [viewport, api] = useEmblaCarousel({ loop: false, direction: environment.direction, startIndex,\n // HJM owns selection; upstream focus scrolling must not independently change slides.\n // Embla's default 25 is a physics duration factor, not an HJM millisecond token.\n watchFocus: false, duration: environment.reducedMotion ? 0 : 25 });\n const latest = useRef(props); latest.current = props;\n const syncing = useRef(false);\n useEffect(() => {\n if (!api) return;\n const select = () => {\n const current = latest.current;\n const item = current.slides[api.selectedScrollSnap()];\n if (!syncing.current && item && item.id !== current.currentKey) current.onCurrentKeyChange(item.id);\n };\n api.on(\"select\", select);\n return () => { api.off(\"select\", select); };\n }, [api]);\n useEffect(() => { syncing.current = true; api?.scrollTo(index, environment.reducedMotion); syncing.current = false; }, [api, index, environment.reducedMotion]);\n return <section aria-label={props.label} aria-roledescription=\"carousel\">\n <div ref={viewport} style={{ overflow: \"hidden\" }}><div style={{ display: \"flex\", touchAction: \"pan-y pinch-zoom\" }}>\n {props.slides.map((slide, i) => <div key={slide.id} role=\"group\" aria-roledescription=\"slide\" aria-label={resolved[i]!.accessibleName} aria-hidden={resolved[i]!.inert} inert={resolved[i]!.inert}\n style={{ flex: \"0 0 100%\", minWidth: 0 }}>{props.renderSlide(slide)}</div>)}\n </div></div>\n <Button tone=\"ghost\" disabled={index === 0} onClick={() => props.onCurrentKeyChange(getCarouselNavigationTarget(descriptor, \"previous\"))}>{props.previousLabel}</Button>\n <Button tone=\"ghost\" disabled={index === props.slides.length - 1} onClick={() => props.onCurrentKeyChange(getCarouselNavigationTarget(descriptor, \"next\"))}>{props.nextLabel}</Button>\n </section>;\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { type CodeBlockDescriptor } from '@hjmds/design-contracts/code-block';
|
|
3
|
+
export type CodeBlockProps = CodeBlockDescriptor & Readonly<{
|
|
4
|
+
copyAction?: ReactNode;
|
|
5
|
+
}>;
|
|
6
|
+
/** Token text is rendered as React text, never executable HTML. */
|
|
7
|
+
export declare function CodeBlock({ copyAction, ...descriptor }: CodeBlockProps): import("react").JSX.Element;
|
|
8
|
+
//# sourceMappingURL=code-block.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-block.d.ts","sourceRoot":"","sources":["../src/code-block.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AACrC,OAAO,EAAkB,KAAK,mBAAmB,EAAC,MAAM,oCAAoC,CAAC;AAC7F,MAAM,MAAM,cAAc,GAAC,mBAAmB,GAAG,QAAQ,CAAC;IAAC,UAAU,CAAC,EAAC,SAAS,CAAA;CAAC,CAAC,CAAC;AAEnF,mEAAmE;AACnE,wBAAgB,SAAS,CAAC,EAAC,UAAU,EAAC,GAAG,UAAU,EAAC,EAAC,cAAc,+BAAwvB"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { resolveCodeBlock } from '@hjmds/design-contracts/code-block';
|
|
3
|
+
const colors = { plain: 'var(--hjm-color-text)', keyword: 'var(--hjm-color-content-brand)', string: 'var(--hjm-color-text)', comment: 'var(--hjm-color-text-muted)', number: 'var(--hjm-color-content-brand)' };
|
|
4
|
+
/** Token text is rendered as React text, never executable HTML. */
|
|
5
|
+
export function CodeBlock({ copyAction, ...descriptor }) { const spec = resolveCodeBlock(descriptor); return _jsxs("section", { "aria-label": spec.label, style: { minWidth: 0, borderRadius: 'var(--hjm-radius-lg)', background: 'var(--hjm-color-surface-alt)', color: 'var(--hjm-color-text)', overflow: 'hidden' }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 'var(--hjm-space-sm)', padding: 'var(--hjm-space-md)' }, children: [_jsx("span", { children: spec.language ?? spec.label }), copyAction] }), _jsx("pre", { tabIndex: 0, "aria-label": spec.label, style: { margin: 0, padding: 'var(--hjm-space-md)', overflowX: 'auto', whiteSpace: spec.wrap ? 'pre-wrap' : 'pre', overflowWrap: spec.wrap ? 'anywhere' : undefined }, children: _jsx("code", { children: spec.tokens.map((token, index) => _jsx("span", { style: { color: colors[token.tone ?? 'plain'] }, children: token.text }, index)) }) })] }); }
|
|
6
|
+
//# sourceMappingURL=code-block.js.map
|