@atelier-ui/react 0.2.14 → 0.2.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/package.json +1 -1
- package/src/lib/accordion/atl-accordion.css +21 -5
- package/src/lib/accordion/atl-accordion.d.ts.map +1 -1
- package/src/lib/accordion/atl-accordion.js +2 -3
- package/src/lib/accordion/atl-accordion.js.map +1 -1
- package/src/lib/alert/atl-alert.css +11 -1
- package/src/lib/alert/atl-alert.d.ts.map +1 -1
- package/src/lib/alert/atl-alert.js +2 -1
- package/src/lib/alert/atl-alert.js.map +1 -1
- package/src/lib/avatar/atl-avatar.css +24 -4
- package/src/lib/avatar/atl-avatar.d.ts.map +1 -1
- package/src/lib/avatar/atl-avatar.js +2 -1
- package/src/lib/avatar/atl-avatar.js.map +1 -1
- package/src/lib/badge/atl-badge.css +16 -6
- package/src/lib/breadcrumbs/atl-breadcrumbs.css +16 -0
- package/src/lib/button/atl-button.css +12 -2
- package/src/lib/card/atl-card.css +29 -4
- package/src/lib/chat/atl-chat.css +44 -15
- package/src/lib/chat/atl-chat.d.ts.map +1 -1
- package/src/lib/chat/atl-chat.js +2 -1
- package/src/lib/chat/atl-chat.js.map +1 -1
- package/src/lib/checkbox/atl-checkbox.css +12 -2
- package/src/lib/checkbox/atl-checkbox.d.ts +1 -5
- package/src/lib/checkbox/atl-checkbox.d.ts.map +1 -1
- package/src/lib/checkbox/atl-checkbox.js +2 -3
- package/src/lib/checkbox/atl-checkbox.js.map +1 -1
- package/src/lib/code-block/atl-code-block.css +27 -8
- package/src/lib/code-block/atl-code-block.d.ts.map +1 -1
- package/src/lib/code-block/atl-code-block.js +2 -1
- package/src/lib/code-block/atl-code-block.js.map +1 -1
- package/src/lib/combobox/atl-combobox.css +56 -5
- package/src/lib/combobox/atl-combobox.d.ts.map +1 -1
- package/src/lib/combobox/atl-combobox.js +4 -2
- package/src/lib/combobox/atl-combobox.js.map +1 -1
- package/src/lib/dialog/atl-dialog.css +28 -4
- package/src/lib/dialog/atl-dialog.d.ts.map +1 -1
- package/src/lib/dialog/atl-dialog.js +2 -1
- package/src/lib/dialog/atl-dialog.js.map +1 -1
- package/src/lib/drawer/atl-drawer.css +31 -4
- package/src/lib/drawer/atl-drawer.d.ts.map +1 -1
- package/src/lib/drawer/atl-drawer.js +2 -1
- package/src/lib/drawer/atl-drawer.js.map +1 -1
- package/src/lib/icon/atl-icon.css +18 -0
- package/src/lib/icon/atl-icon.d.ts +2 -1
- package/src/lib/icon/atl-icon.d.ts.map +1 -1
- package/src/lib/icon/atl-icon.js +6 -25
- package/src/lib/icon/atl-icon.js.map +1 -1
- package/src/lib/icons.d.ts +39 -0
- package/src/lib/icons.d.ts.map +1 -0
- package/src/lib/icons.js +49 -0
- package/src/lib/icons.js.map +1 -0
- package/src/lib/input/atl-input.css +21 -7
- package/src/lib/input/atl-input.d.ts.map +1 -1
- package/src/lib/input/atl-input.js +2 -1
- package/src/lib/input/atl-input.js.map +1 -1
- package/src/lib/menu/atl-menu.css +28 -3
- package/src/lib/pagination/atl-pagination.css +11 -1
- package/src/lib/progress/atl-progress.css +10 -0
- package/src/lib/radio/atl-radio.css +11 -1
- package/src/lib/radio/atl-radio.d.ts.map +1 -1
- package/src/lib/radio/atl-radio.js +5 -3
- package/src/lib/radio/atl-radio.js.map +1 -1
- package/src/lib/radio-group/atl-radio-group.css +10 -0
- package/src/lib/select/atl-select.css +21 -3
- package/src/lib/select/atl-select.d.ts +1 -5
- package/src/lib/select/atl-select.d.ts.map +1 -1
- package/src/lib/select/atl-select.js +1 -3
- package/src/lib/select/atl-select.js.map +1 -1
- package/src/lib/skeleton/atl-skeleton.css +15 -0
- package/src/lib/spec.d.ts +20 -6
- package/src/lib/spec.d.ts.map +1 -1
- package/src/lib/spec.js +1 -1
- package/src/lib/spec.js.map +1 -1
- package/src/lib/stepper/atl-stepper.css +11 -1
- package/src/lib/stepper/atl-stepper.d.ts.map +1 -1
- package/src/lib/stepper/atl-stepper.js +2 -1
- package/src/lib/stepper/atl-stepper.js.map +1 -1
- package/src/lib/table/atl-table.css +42 -3
- package/src/lib/table/atl-table.d.ts.map +1 -1
- package/src/lib/table/atl-table.js +2 -1
- package/src/lib/table/atl-table.js.map +1 -1
- package/src/lib/tabs/atl-tabs.css +27 -5
- package/src/lib/textarea/atl-textarea.css +22 -7
- package/src/lib/textarea/atl-textarea.d.ts.map +1 -1
- package/src/lib/textarea/atl-textarea.js +2 -1
- package/src/lib/textarea/atl-textarea.js.map +1 -1
- package/src/lib/toast/atl-toast.css +21 -0
- package/src/lib/toast/atl-toast.d.ts.map +1 -1
- package/src/lib/toast/atl-toast.js +2 -1
- package/src/lib/toast/atl-toast.js.map +1 -1
- package/src/lib/toggle/atl-toggle.css +11 -1
- package/src/lib/toggle/atl-toggle.d.ts +1 -5
- package/src/lib/toggle/atl-toggle.d.ts.map +1 -1
- package/src/lib/toggle/atl-toggle.js +2 -3
- package/src/lib/toggle/atl-toggle.js.map +1 -1
- package/src/lib/tooltip/atl-tooltip.css +21 -0
- package/styles/tokens.css +12 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useId, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import './atl-combobox.css';
|
|
4
|
+
import { AtlIcon } from '../icon/atl-icon';
|
|
4
5
|
/**
|
|
5
6
|
* Filterable autocomplete combobox. Accepts an `options` array and emits the
|
|
6
7
|
* selected option's `value`. The user types to narrow the list; selecting an
|
|
@@ -122,18 +123,19 @@ export function AtlCombobox({ value = '', onValueChange, options = [], placehold
|
|
|
122
123
|
'atl-combobox',
|
|
123
124
|
isOpen && 'is-open',
|
|
124
125
|
disabled && 'is-disabled',
|
|
126
|
+
readonly && 'is-readonly',
|
|
125
127
|
invalid && 'is-invalid',
|
|
126
128
|
]
|
|
127
129
|
.filter(Boolean)
|
|
128
130
|
.join(' ');
|
|
129
131
|
const activeOptionId = activeIndex >= 0 ? `${panelId}-option-${activeIndex}` : undefined;
|
|
130
|
-
return (_jsxs("div", { className: classes, ref: containerRef, children: [_jsxs("div", { className: "atl-combobox-wrapper", children: [_jsx("input", { ref: inputRef, className: "atl-combobox-input", type: "text", autoComplete: "off", role: "combobox", id: inputId, "aria-expanded": isOpen, "aria-controls": panelId, "aria-autocomplete": "list", "aria-activedescendant": activeOptionId, "aria-invalid": invalid || undefined, disabled: disabled, readOnly: readonly, required: required, name: name, placeholder: placeholder, value: displayValue, onChange: handleInput, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeydown }), _jsx("span", { className: "atl-combobox-icon", "aria-hidden": "true", children: _jsx(
|
|
132
|
+
return (_jsxs("div", { className: classes, ref: containerRef, children: [_jsxs("div", { className: "atl-combobox-wrapper", children: [_jsx("input", { ref: inputRef, className: "atl-combobox-input", type: "text", autoComplete: "off", role: "combobox", id: inputId, "aria-expanded": isOpen, "aria-controls": panelId, "aria-autocomplete": "list", "aria-activedescendant": activeOptionId, "aria-invalid": invalid || undefined, disabled: disabled, readOnly: readonly, required: required, name: name, placeholder: placeholder, value: displayValue, onChange: handleInput, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeydown }), _jsx("span", { className: "atl-combobox-icon", "aria-hidden": "true", children: _jsx(AtlIcon, { name: "chevron-down", size: "sm" }) })] }), isOpen && (_jsx("ul", { id: panelId, className: "atl-combobox-panel", role: "listbox", "aria-labelledby": inputId, children: filteredOptions.length > 0 ? (filteredOptions.map((option, i) => (_jsxs("li", { id: `${panelId}-option-${i}`, role: "option", className: [
|
|
131
133
|
'atl-combobox-option',
|
|
132
134
|
activeIndex === i && 'is-active',
|
|
133
135
|
option.value === value && 'is-selected',
|
|
134
136
|
option.disabled && 'is-disabled',
|
|
135
137
|
]
|
|
136
138
|
.filter(Boolean)
|
|
137
|
-
.join(' '), "aria-selected": option.value === value, "aria-disabled": option.disabled || undefined, onMouseDown: () => selectOption(option), onMouseEnter: () => setActiveIndex(i), children: [_jsx("span", { children: option.label }), option.value === value && (_jsx(
|
|
139
|
+
.join(' '), "aria-selected": option.value === value, "aria-disabled": option.disabled || undefined, onMouseDown: () => selectOption(option), onMouseEnter: () => setActiveIndex(i), children: [_jsx("span", { children: option.label }), option.value === value && (_jsx(AtlIcon, { name: "check", size: "sm", className: "atl-combobox-check" }))] }, option.value)))) : (_jsx("li", { className: "atl-combobox-no-results", role: "option", "aria-selected": false, "aria-disabled": "true", children: "No results found." })) })), invalid && errors.length > 0 && (_jsx("div", { className: "atl-combobox-errors", role: "alert", "aria-live": "polite", children: errors.map((e, i) => (_jsx("p", { className: "atl-combobox-error-message", children: e }, i))) }))] }));
|
|
138
140
|
}
|
|
139
141
|
//# sourceMappingURL=atl-combobox.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atl-combobox.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/combobox/atl-combobox.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useId, useMemo, useRef, useState } from 'react';\nimport type { AtlComboboxOption, AtlComboboxSpec } from '../spec';\nimport './atl-combobox.css';\n\nexport type { AtlComboboxOption };\n\nexport interface AtlComboboxProps extends AtlComboboxSpec {\n value?: string;\n onValueChange?: (value: string) => void;\n errors?: string[];\n}\n\n/**\n * Filterable autocomplete combobox. Accepts an `options` array and emits the\n * selected option's `value`. The user types to narrow the list; selecting an\n * option commits the value and displays its label.\n *\n * Usage:\n * ```tsx\n * <AtlCombobox\n * value={country}\n * onValueChange={setCountry}\n * options={countryOptions}\n * placeholder=\"Search country…\"\n * />\n * ```\n */\nexport function AtlCombobox({\n value = '',\n onValueChange,\n options = [],\n placeholder = '',\n disabled = false,\n readonly = false,\n invalid = false,\n required = false,\n name,\n errors = [],\n}: AtlComboboxProps) {\n const [query, setQuery] = useState('');\n const [isOpen, setIsOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState(-1);\n\n const inputRef = useRef<HTMLInputElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const inputId = useId();\n const panelId = useId();\n\n const selectedLabel = useMemo(\n () => options.find((o) => o.value === value)?.label ?? '',\n [options, value],\n );\n\n const filteredOptions = useMemo(() => {\n if (!query) return options;\n const q = query.toLowerCase();\n return options.filter((o) => o.label.toLowerCase().includes(q));\n }, [options, query]);\n\n const displayValue = isOpen ? query : selectedLabel;\n\n // Outside-click closes panel\n useEffect(() => {\n if (!isOpen) return;\n function handleClick(e: MouseEvent) {\n if (!containerRef.current?.contains(e.target as Node)) {\n setIsOpen(false);\n setQuery(selectedLabel);\n }\n }\n document.addEventListener('click', handleClick);\n return () => document.removeEventListener('click', handleClick);\n }, [isOpen, selectedLabel]);\n\n function open() {\n if (disabled || readonly) return;\n setQuery(selectedLabel);\n setIsOpen(true);\n setActiveIndex(-1);\n }\n\n function close() {\n setIsOpen(false);\n setActiveIndex(-1);\n }\n\n function selectOption(option: AtlComboboxOption) {\n if (option.disabled || disabled || readonly) return;\n onValueChange?.(option.value);\n setQuery(option.label);\n close();\n inputRef.current?.focus();\n }\n\n function handleInput(e: React.ChangeEvent<HTMLInputElement>) {\n const q = e.target.value;\n setQuery(q);\n setActiveIndex(-1);\n if (q === '') onValueChange?.('');\n if (!isOpen) open();\n }\n\n function handleFocus() {\n open();\n }\n\n function handleBlur() {\n setQuery(selectedLabel);\n }\n\n function handleKeydown(e: React.KeyboardEvent) {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n if (!isOpen) { open(); return; }\n setActiveIndex((i) => (i + 1 >= filteredOptions.length ? 0 : i + 1));\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n if (!isOpen) { open(); return; }\n setActiveIndex((i) => (i - 1 < 0 ? filteredOptions.length - 1 : i - 1));\n break;\n }\n case 'Enter': {\n e.preventDefault();\n if (isOpen && activeIndex >= 0 && activeIndex < filteredOptions.length) {\n selectOption(filteredOptions[activeIndex]);\n }\n break;\n }\n case 'Escape': {\n e.preventDefault();\n setQuery(selectedLabel);\n close();\n break;\n }\n case 'Tab': {\n close();\n break;\n }\n }\n }\n\n const classes = [\n 'atl-combobox',\n isOpen && 'is-open',\n disabled && 'is-disabled',\n invalid && 'is-invalid',\n ]\n .filter(Boolean)\n .join(' ');\n\n const activeOptionId =\n activeIndex >= 0 ? `${panelId}-option-${activeIndex}` : undefined;\n\n return (\n <div className={classes} ref={containerRef}>\n <div className=\"atl-combobox-wrapper\">\n <input\n ref={inputRef}\n className=\"atl-combobox-input\"\n type=\"text\"\n autoComplete=\"off\"\n role=\"combobox\"\n id={inputId}\n aria-expanded={isOpen}\n aria-controls={panelId}\n aria-autocomplete=\"list\"\n aria-activedescendant={activeOptionId}\n aria-invalid={invalid || undefined}\n disabled={disabled}\n readOnly={readonly}\n required={required}\n name={name}\n placeholder={placeholder}\n value={displayValue}\n onChange={handleInput}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleKeydown}\n />\n <span className=\"atl-combobox-icon\" aria-hidden=\"true\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n <path d=\"M2 4l4 4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </span>\n </div>\n\n {isOpen && (\n <ul\n id={panelId}\n className=\"atl-combobox-panel\"\n role=\"listbox\"\n aria-labelledby={inputId}\n >\n {filteredOptions.length > 0 ? (\n filteredOptions.map((option, i) => (\n <li\n key={option.value}\n id={`${panelId}-option-${i}`}\n role=\"option\"\n className={[\n 'atl-combobox-option',\n activeIndex === i && 'is-active',\n option.value === value && 'is-selected',\n option.disabled && 'is-disabled',\n ]\n .filter(Boolean)\n .join(' ')}\n aria-selected={option.value === value}\n aria-disabled={option.disabled || undefined}\n onMouseDown={() => selectOption(option)}\n onMouseEnter={() => setActiveIndex(i)}\n >\n <span>{option.label}</span>\n {option.value === value && (\n <svg className=\"atl-combobox-check\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M2 7l4 4 6-7\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )}\n </li>\n ))\n ) : (\n <li className=\"atl-combobox-no-results\" role=\"option\" aria-selected={false} aria-disabled=\"true\">\n No results found.\n </li>\n )}\n </ul>\n )}\n\n {invalid && errors.length > 0 && (\n <div className=\"atl-combobox-errors\" role=\"alert\" aria-live=\"polite\">\n {errors.map((e, i) => (\n <p key={i} className=\"atl-combobox-error-message\">{e}</p>\n ))}\n </div>\n )}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"atl-combobox.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/combobox/atl-combobox.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useId, useMemo, useRef, useState } from 'react';\nimport type { AtlComboboxOption, AtlComboboxSpec } from '../spec';\nimport './atl-combobox.css';\nimport { AtlIcon } from '../icon/atl-icon';\n\nexport type { AtlComboboxOption };\n\nexport interface AtlComboboxProps extends AtlComboboxSpec {\n value?: string;\n onValueChange?: (value: string) => void;\n errors?: string[];\n}\n\n/**\n * Filterable autocomplete combobox. Accepts an `options` array and emits the\n * selected option's `value`. The user types to narrow the list; selecting an\n * option commits the value and displays its label.\n *\n * Usage:\n * ```tsx\n * <AtlCombobox\n * value={country}\n * onValueChange={setCountry}\n * options={countryOptions}\n * placeholder=\"Search country…\"\n * />\n * ```\n */\nexport function AtlCombobox({\n value = '',\n onValueChange,\n options = [],\n placeholder = '',\n disabled = false,\n readonly = false,\n invalid = false,\n required = false,\n name,\n errors = [],\n}: AtlComboboxProps) {\n const [query, setQuery] = useState('');\n const [isOpen, setIsOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState(-1);\n\n const inputRef = useRef<HTMLInputElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const inputId = useId();\n const panelId = useId();\n\n const selectedLabel = useMemo(\n () => options.find((o) => o.value === value)?.label ?? '',\n [options, value],\n );\n\n const filteredOptions = useMemo(() => {\n if (!query) return options;\n const q = query.toLowerCase();\n return options.filter((o) => o.label.toLowerCase().includes(q));\n }, [options, query]);\n\n const displayValue = isOpen ? query : selectedLabel;\n\n // Outside-click closes panel\n useEffect(() => {\n if (!isOpen) return;\n function handleClick(e: MouseEvent) {\n if (!containerRef.current?.contains(e.target as Node)) {\n setIsOpen(false);\n setQuery(selectedLabel);\n }\n }\n document.addEventListener('click', handleClick);\n return () => document.removeEventListener('click', handleClick);\n }, [isOpen, selectedLabel]);\n\n function open() {\n if (disabled || readonly) return;\n setQuery(selectedLabel);\n setIsOpen(true);\n setActiveIndex(-1);\n }\n\n function close() {\n setIsOpen(false);\n setActiveIndex(-1);\n }\n\n function selectOption(option: AtlComboboxOption) {\n if (option.disabled || disabled || readonly) return;\n onValueChange?.(option.value);\n setQuery(option.label);\n close();\n inputRef.current?.focus();\n }\n\n function handleInput(e: React.ChangeEvent<HTMLInputElement>) {\n const q = e.target.value;\n setQuery(q);\n setActiveIndex(-1);\n if (q === '') onValueChange?.('');\n if (!isOpen) open();\n }\n\n function handleFocus() {\n open();\n }\n\n function handleBlur() {\n setQuery(selectedLabel);\n }\n\n function handleKeydown(e: React.KeyboardEvent) {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n if (!isOpen) { open(); return; }\n setActiveIndex((i) => (i + 1 >= filteredOptions.length ? 0 : i + 1));\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n if (!isOpen) { open(); return; }\n setActiveIndex((i) => (i - 1 < 0 ? filteredOptions.length - 1 : i - 1));\n break;\n }\n case 'Enter': {\n e.preventDefault();\n if (isOpen && activeIndex >= 0 && activeIndex < filteredOptions.length) {\n selectOption(filteredOptions[activeIndex]);\n }\n break;\n }\n case 'Escape': {\n e.preventDefault();\n setQuery(selectedLabel);\n close();\n break;\n }\n case 'Tab': {\n close();\n break;\n }\n }\n }\n\n const classes = [\n 'atl-combobox',\n isOpen && 'is-open',\n disabled && 'is-disabled',\n readonly && 'is-readonly',\n invalid && 'is-invalid',\n ]\n .filter(Boolean)\n .join(' ');\n\n const activeOptionId =\n activeIndex >= 0 ? `${panelId}-option-${activeIndex}` : undefined;\n\n return (\n <div className={classes} ref={containerRef}>\n <div className=\"atl-combobox-wrapper\">\n <input\n ref={inputRef}\n className=\"atl-combobox-input\"\n type=\"text\"\n autoComplete=\"off\"\n role=\"combobox\"\n id={inputId}\n aria-expanded={isOpen}\n aria-controls={panelId}\n aria-autocomplete=\"list\"\n aria-activedescendant={activeOptionId}\n aria-invalid={invalid || undefined}\n disabled={disabled}\n readOnly={readonly}\n required={required}\n name={name}\n placeholder={placeholder}\n value={displayValue}\n onChange={handleInput}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleKeydown}\n />\n <span className=\"atl-combobox-icon\" aria-hidden=\"true\">\n <AtlIcon name=\"chevron-down\" size=\"sm\" />\n </span>\n </div>\n\n {isOpen && (\n <ul\n id={panelId}\n className=\"atl-combobox-panel\"\n role=\"listbox\"\n aria-labelledby={inputId}\n >\n {filteredOptions.length > 0 ? (\n filteredOptions.map((option, i) => (\n <li\n key={option.value}\n id={`${panelId}-option-${i}`}\n role=\"option\"\n className={[\n 'atl-combobox-option',\n activeIndex === i && 'is-active',\n option.value === value && 'is-selected',\n option.disabled && 'is-disabled',\n ]\n .filter(Boolean)\n .join(' ')}\n aria-selected={option.value === value}\n aria-disabled={option.disabled || undefined}\n onMouseDown={() => selectOption(option)}\n onMouseEnter={() => setActiveIndex(i)}\n >\n <span>{option.label}</span>\n {option.value === value && (\n <AtlIcon name=\"check\" size=\"sm\" className=\"atl-combobox-check\" />\n )}\n </li>\n ))\n ) : (\n <li className=\"atl-combobox-no-results\" role=\"option\" aria-selected={false} aria-disabled=\"true\">\n No results found.\n </li>\n )}\n </ul>\n )}\n\n {invalid && errors.length > 0 && (\n <div className=\"atl-combobox-errors\" role=\"alert\" aria-live=\"polite\">\n {errors.map((e, i) => (\n <p key={i} className=\"atl-combobox-error-message\">{e}</p>\n ))}\n </div>\n )}\n </div>\n );\n}\n"]}
|
|
@@ -1,6 +1,30 @@
|
|
|
1
|
+
/* Geometry contract: every size this component states is a border-box size.
|
|
2
|
+
* Declared with the component rather than as a global reset, so it ships in the
|
|
3
|
+
* same file as the sizes it governs and no consuming app has to supply one.
|
|
4
|
+
* Gated by check:box-sizing; the resulting boxes are measured by check:geometry.
|
|
5
|
+
* See ADR-0043. */
|
|
6
|
+
:is(
|
|
7
|
+
.atl-dialog,
|
|
8
|
+
.atl-dialog-content,
|
|
9
|
+
.atl-dialog-footer,
|
|
10
|
+
.atl-dialog-header
|
|
11
|
+
),
|
|
12
|
+
:is(
|
|
13
|
+
.atl-dialog,
|
|
14
|
+
.atl-dialog-content,
|
|
15
|
+
.atl-dialog-footer,
|
|
16
|
+
.atl-dialog-header
|
|
17
|
+
) * {
|
|
18
|
+
box-sizing: border-box;
|
|
19
|
+
}
|
|
20
|
+
|
|
1
21
|
/* ── Native <dialog> reset + base ──────────────────────────────────────────── */
|
|
2
22
|
.atl-dialog {
|
|
3
23
|
all: unset;
|
|
24
|
+
/* After `all: unset`, which would otherwise reset it. The library states its own
|
|
25
|
+
* typeface (ADR-0035); without this the dialog renders in the consuming app's
|
|
26
|
+
* font while its neighbours render Instrument Sans (ADR-0049). */
|
|
27
|
+
font-family: var(--ui-font-family);
|
|
4
28
|
position: fixed;
|
|
5
29
|
inset: 0;
|
|
6
30
|
margin: auto;
|
|
@@ -116,7 +140,7 @@ dialog > .panel.size-full {
|
|
|
116
140
|
align-items: center;
|
|
117
141
|
justify-content: space-between;
|
|
118
142
|
padding: var(--ui-spacing-5) var(--ui-spacing-6);
|
|
119
|
-
border-bottom:
|
|
143
|
+
border-bottom: var(--ui-border-width) solid var(--ui-color-border);
|
|
120
144
|
font-size: var(--ui-font-size-xl);
|
|
121
145
|
font-weight: 600;
|
|
122
146
|
letter-spacing: var(--ui-letter-spacing-tight);
|
|
@@ -138,7 +162,7 @@ dialog > .panel.size-full {
|
|
|
138
162
|
justify-content: flex-end;
|
|
139
163
|
gap: var(--ui-spacing-3);
|
|
140
164
|
padding: var(--ui-spacing-5) var(--ui-spacing-6);
|
|
141
|
-
border-top:
|
|
165
|
+
border-top: var(--ui-border-width) solid var(--ui-color-border);
|
|
142
166
|
flex-shrink: 0;
|
|
143
167
|
}
|
|
144
168
|
|
|
@@ -148,8 +172,8 @@ dialog > .panel.size-full {
|
|
|
148
172
|
align-items: center;
|
|
149
173
|
justify-content: center;
|
|
150
174
|
flex-shrink: 0;
|
|
151
|
-
width:
|
|
152
|
-
height:
|
|
175
|
+
width: var(--ui-control-height-sm);
|
|
176
|
+
height: var(--ui-control-height-sm);
|
|
153
177
|
padding: 0;
|
|
154
178
|
margin-left: var(--ui-spacing-3);
|
|
155
179
|
background: transparent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atl-dialog.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/dialog/atl-dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,SAAS,EACT,cAAc,EAEf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"atl-dialog.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/dialog/atl-dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,SAAS,EACT,cAAc,EAEf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,kBAAkB,CAAC;AAa1B;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD;;OAEG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;OAEG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;IAC1C;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAY,EACZ,YAAY,EACZ,eAAsB,EACtB,IAAW,EACX,YAAY,EAAE,SAAS,EACvB,iBAAiB,EAAE,cAAc,EACjC,QAAQ,GACT,EAAE,cAAc,+BA2DhB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG;IAClC;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,+BAmBA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG;IAClC;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,+BASA;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG;IAClC;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,+BASA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef, useId, createContext, useContext, } from 'react';
|
|
3
3
|
import './atl-dialog.css';
|
|
4
|
+
import { AtlIcon } from '../icon/atl-icon';
|
|
4
5
|
const DialogContext = createContext({
|
|
5
6
|
headerId: '',
|
|
6
7
|
close: () => undefined,
|
|
@@ -59,7 +60,7 @@ export function AtlDialog({ open = false, onOpenChange, closeOnBackdrop = true,
|
|
|
59
60
|
*/
|
|
60
61
|
export function AtlDialogHeader({ children, className, ...rest }) {
|
|
61
62
|
const ctx = useContext(DialogContext);
|
|
62
|
-
return (_jsxs("div", { id: ctx.headerId, className: ['atl-dialog-header', className].filter(Boolean).join(' '), ...rest, children: [children, _jsx("button", { className: "close-btn", type: "button", "aria-label": "Close dialog", onClick: ctx.close, children:
|
|
63
|
+
return (_jsxs("div", { id: ctx.headerId, className: ['atl-dialog-header', className].filter(Boolean).join(' '), ...rest, children: [children, _jsx("button", { className: "close-btn", type: "button", "aria-label": "Close dialog", onClick: ctx.close, children: _jsx(AtlIcon, { name: "close", size: "sm" }) })] }));
|
|
63
64
|
}
|
|
64
65
|
/**
|
|
65
66
|
* The main content component for an AtlDialog.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atl-dialog.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/dialog/atl-dialog.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,SAAS,EACT,MAAM,EACN,KAAK,EACL,aAAa,EACb,UAAU,GAIX,MAAM,OAAO,CAAC;AAEf,OAAO,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"atl-dialog.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/dialog/atl-dialog.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useEffect,\n useRef,\n useId,\n createContext,\n useContext,\n ReactNode,\n HTMLAttributes,\n MouseEvent,\n} from 'react';\nimport type { AtlDialogSpec } from '../spec';\nimport './atl-dialog.css';\nimport { AtlIcon } from '../icon/atl-icon';\n\ninterface DialogContextValue {\n headerId: string;\n close: () => void;\n}\n\nconst DialogContext = createContext<DialogContextValue>({\n headerId: '',\n close: () => undefined,\n});\n\n/**\n * Properties for the AtlDialog component.\n */\nexport interface AtlDialogProps extends AtlDialogSpec {\n /**\n * Whether the dialog is open.\n */\n open?: boolean;\n /**\n * Callback triggered when the open state changes.\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * Whether to close the dialog when clicking on the backdrop.\n */\n closeOnBackdrop?: boolean;\n /**\n * The size of the dialog.\n */\n size?: 'sm' | 'md' | 'lg' | 'xl' | 'full';\n /**\n * Accessible label for the dialog.\n */\n 'aria-label'?: string;\n /**\n * Accessible label provided by another element.\n */\n 'aria-labelledby'?: string;\n /**\n * The content of the dialog.\n */\n children?: ReactNode;\n}\n\n/**\n * A dialog (modal) component for displaying content on top of the main UI.\n */\nexport function AtlDialog({\n open = false,\n onOpenChange,\n closeOnBackdrop = true,\n size = 'md',\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n children,\n}: AtlDialogProps) {\n const dialogRef = useRef<HTMLDialogElement>(null);\n const headerId = useId();\n const triggerElRef = useRef<Element | null>(null);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n if (open) {\n triggerElRef.current = document.activeElement;\n if (!dialog.open) dialog.showModal();\n } else {\n if (dialog.open) dialog.close();\n (triggerElRef.current as HTMLElement | null)?.focus();\n triggerElRef.current = null;\n }\n }, [open]);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n const onClose = () => onOpenChange?.(false);\n const onCancel = (e: Event) => {\n e.preventDefault();\n onOpenChange?.(false);\n };\n dialog.addEventListener('close', onClose);\n dialog.addEventListener('cancel', onCancel);\n return () => {\n dialog.removeEventListener('close', onClose);\n dialog.removeEventListener('cancel', onCancel);\n };\n }, [onOpenChange]);\n\n const handleBackdropClick = (e: MouseEvent<HTMLDialogElement>) => {\n if (!closeOnBackdrop) return;\n if (e.target === dialogRef.current) {\n onOpenChange?.(false);\n }\n };\n\n const effectiveAriaLabelledby = ariaLabel ? undefined : (ariaLabelledby ?? headerId);\n\n return (\n <DialogContext.Provider value={{ headerId, close: () => onOpenChange?.(false) }}>\n <dialog\n ref={dialogRef}\n className={`atl-dialog size-${size}${open ? ' is-open' : ''}`}\n aria-label={ariaLabel || undefined}\n aria-labelledby={effectiveAriaLabelledby}\n aria-modal=\"true\"\n onClick={handleBackdropClick}\n >\n <div className=\"panel\" onClick={(e) => e.stopPropagation()}>\n {children}\n </div>\n </dialog>\n </DialogContext.Provider>\n );\n}\n\n/**\n * The header component for an AtlDialog.\n */\nexport function AtlDialogHeader({\n children,\n className,\n ...rest\n}: HTMLAttributes<HTMLDivElement> & {\n /**\n * The content of the dialog header.\n */\n children?: ReactNode;\n}) {\n const ctx = useContext(DialogContext);\n return (\n <div\n id={ctx.headerId}\n className={['atl-dialog-header', className].filter(Boolean).join(' ')}\n {...rest}\n >\n {children}\n <button\n className=\"close-btn\"\n type=\"button\"\n aria-label=\"Close dialog\"\n onClick={ctx.close}\n >\n <AtlIcon name=\"close\" size=\"sm\" />\n </button>\n </div>\n );\n}\n\n/**\n * The main content component for an AtlDialog.\n */\nexport function AtlDialogContent({\n children,\n className,\n ...rest\n}: HTMLAttributes<HTMLDivElement> & {\n /**\n * The main content of the dialog.\n */\n children?: ReactNode;\n}) {\n return (\n <div\n className={['atl-dialog-content', className].filter(Boolean).join(' ')}\n {...rest}\n >\n {children}\n </div>\n );\n}\n\n/**\n * The footer component for an AtlDialog.\n */\nexport function AtlDialogFooter({\n children,\n className,\n ...rest\n}: HTMLAttributes<HTMLDivElement> & {\n /**\n * The content of the dialog footer.\n */\n children?: ReactNode;\n}) {\n return (\n <div\n className={['atl-dialog-footer', className].filter(Boolean).join(' ')}\n {...rest}\n >\n {children}\n </div>\n );\n}\n"]}
|
|
@@ -1,11 +1,38 @@
|
|
|
1
|
+
/* Geometry contract: every size this component states is a border-box size.
|
|
2
|
+
* Declared with the component rather than as a global reset, so it ships in the
|
|
3
|
+
* same file as the sizes it governs and no consuming app has to supply one.
|
|
4
|
+
* Gated by check:box-sizing; the resulting boxes are measured by check:geometry.
|
|
5
|
+
* See ADR-0043. */
|
|
6
|
+
:is(
|
|
7
|
+
.atl-drawer-content,
|
|
8
|
+
.atl-drawer-footer,
|
|
9
|
+
.atl-drawer-header,
|
|
10
|
+
.atl-drawer-host
|
|
11
|
+
),
|
|
12
|
+
:is(
|
|
13
|
+
.atl-drawer-content,
|
|
14
|
+
.atl-drawer-footer,
|
|
15
|
+
.atl-drawer-header,
|
|
16
|
+
.atl-drawer-host
|
|
17
|
+
) * {
|
|
18
|
+
box-sizing: border-box;
|
|
19
|
+
}
|
|
20
|
+
|
|
1
21
|
/* ── Host wrapper ──────────────────────────────────────────────────────────── */
|
|
2
22
|
.atl-drawer-host {
|
|
23
|
+
/* The library states its own typeface (ADR-0035). Without this the component
|
|
24
|
+
* renders in the consuming app's font while its neighbours render Instrument
|
|
25
|
+
* Sans — measured: a card next to a button showed two typefaces. Declared once
|
|
26
|
+
* per component root, never on a descendant (ADR-0049). */
|
|
27
|
+
font-family: var(--ui-font-family);
|
|
3
28
|
display: contents;
|
|
4
29
|
}
|
|
5
30
|
|
|
6
31
|
/* ── Native <dialog> base ──────────────────────────────────────────────────── */
|
|
7
32
|
.atl-drawer-host dialog {
|
|
8
33
|
all: unset;
|
|
34
|
+
/* After `all: unset`, which would otherwise reset it (ADR-0049). */
|
|
35
|
+
font-family: var(--ui-font-family);
|
|
9
36
|
position: fixed;
|
|
10
37
|
display: none;
|
|
11
38
|
flex-direction: column;
|
|
@@ -170,7 +197,7 @@
|
|
|
170
197
|
align-items: center;
|
|
171
198
|
justify-content: space-between;
|
|
172
199
|
padding: var(--ui-spacing-5) var(--ui-spacing-6);
|
|
173
|
-
border-bottom:
|
|
200
|
+
border-bottom: var(--ui-border-width) solid var(--ui-color-border);
|
|
174
201
|
font-size: var(--ui-font-size-xl);
|
|
175
202
|
font-weight: 600;
|
|
176
203
|
letter-spacing: var(--ui-letter-spacing-tight);
|
|
@@ -192,7 +219,7 @@
|
|
|
192
219
|
justify-content: flex-end;
|
|
193
220
|
gap: var(--ui-spacing-3);
|
|
194
221
|
padding: var(--ui-spacing-5) var(--ui-spacing-6);
|
|
195
|
-
border-top:
|
|
222
|
+
border-top: var(--ui-border-width) solid var(--ui-color-border);
|
|
196
223
|
flex-shrink: 0;
|
|
197
224
|
}
|
|
198
225
|
|
|
@@ -202,8 +229,8 @@
|
|
|
202
229
|
align-items: center;
|
|
203
230
|
justify-content: center;
|
|
204
231
|
flex-shrink: 0;
|
|
205
|
-
width:
|
|
206
|
-
height:
|
|
232
|
+
width: var(--ui-control-height-sm);
|
|
233
|
+
height: var(--ui-control-height-sm);
|
|
207
234
|
padding: 0;
|
|
208
235
|
margin-left: var(--ui-spacing-3);
|
|
209
236
|
background: transparent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atl-drawer.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/drawer/atl-drawer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,SAAS,EACT,cAAc,EAEf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"atl-drawer.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/drawer/atl-drawer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,SAAS,EACT,cAAc,EAEf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,kBAAkB,CAAC;AAa1B;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD;;OAEG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC/C;;OAEG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;IACnC;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAY,EACZ,YAAY,EACZ,QAAkB,EAClB,IAAW,EACX,eAAsB,EACtB,QAAQ,GACT,EAAE,cAAc,+BAkEhB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG;IAClC;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,+BAmBA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG;IAClC;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,+BASA;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG;IAClC;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,+BASA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef, useId, createContext, useContext, } from 'react';
|
|
3
3
|
import './atl-drawer.css';
|
|
4
|
+
import { AtlIcon } from '../icon/atl-icon';
|
|
4
5
|
const DrawerContext = createContext({
|
|
5
6
|
headerId: '',
|
|
6
7
|
close: () => undefined,
|
|
@@ -66,7 +67,7 @@ export function AtlDrawer({ open = false, onOpenChange, position = 'right', size
|
|
|
66
67
|
*/
|
|
67
68
|
export function AtlDrawerHeader({ children, className, ...rest }) {
|
|
68
69
|
const ctx = useContext(DrawerContext);
|
|
69
|
-
return (_jsxs("div", { id: ctx.headerId, className: ['atl-drawer-header', className].filter(Boolean).join(' '), ...rest, children: [children, _jsx("button", { className: "close-btn", type: "button", "aria-label": "Close drawer", onClick: ctx.close, children:
|
|
70
|
+
return (_jsxs("div", { id: ctx.headerId, className: ['atl-drawer-header', className].filter(Boolean).join(' '), ...rest, children: [children, _jsx("button", { className: "close-btn", type: "button", "aria-label": "Close drawer", onClick: ctx.close, children: _jsx(AtlIcon, { name: "close", size: "sm" }) })] }));
|
|
70
71
|
}
|
|
71
72
|
/**
|
|
72
73
|
* The main content component for an AtlDrawer.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atl-drawer.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/drawer/atl-drawer.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,SAAS,EACT,MAAM,EACN,KAAK,EACL,aAAa,EACb,UAAU,GAIX,MAAM,OAAO,CAAC;AAEf,OAAO,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"atl-drawer.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/drawer/atl-drawer.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,SAAS,EACT,MAAM,EACN,KAAK,EACL,aAAa,EACb,UAAU,GAIX,MAAM,OAAO,CAAC;AAEf,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAO3C,MAAM,aAAa,GAAG,aAAa,CAAqB;IACtD,QAAQ,EAAE,EAAE;IACZ,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS;CACvB,CAAC,CAAC;AAgCH;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,EACxB,IAAI,GAAG,KAAK,EACZ,YAAY,EACZ,QAAQ,GAAG,OAAO,EAClB,IAAI,GAAG,IAAI,EACX,eAAe,GAAG,IAAI,EACtB,QAAQ,GACO;IACf,MAAM,SAAS,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,KAAK,EAAE,CAAC;IACzB,MAAM,YAAY,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAElD,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC;QACjC,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,IAAI,IAAI,EAAE,CAAC;YACT,YAAY,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC;YAC9C,IAAI,CAAC,MAAM,CAAC,IAAI;gBAAE,MAAM,CAAC,SAAS,EAAE,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,IAAI,MAAM,CAAC,IAAI;gBAAE,MAAM,CAAC,KAAK,EAAE,CAAC;YAC/B,YAAY,CAAC,OAA8B,EAAE,KAAK,EAAE,CAAC;YACtD,YAAY,CAAC,OAAO,GAAG,IAAI,CAAC;QAC9B,CAAC;IACH,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC;QACjC,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAG,CAAC,CAAQ,EAAE,EAAE;YAC5B,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC,CAAC;QACF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1C,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC5C,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACjD,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IAEnB,MAAM,mBAAmB,GAAG,CAAC,CAAgC,EAAE,EAAE;QAC/D,IAAI,CAAC,eAAe;YAAE,OAAO;QAC7B,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,OAAO,EAAE,CAAC;YACnC,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG;QAChB,iBAAiB;QACjB,YAAY,QAAQ,EAAE;QACtB,QAAQ,IAAI,EAAE;QACd,IAAI,IAAI,SAAS;KAClB;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,OAAO,CACL,KAAC,aAAa,CAAC,QAAQ,IAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,EAAE,YAC7E,cAAK,SAAS,EAAE,SAAS,YACvB,iBACE,GAAG,EAAE,SAAS,qBACG,QAAQ,gBACd,MAAM,EACjB,OAAO,EAAE,mBAAmB,YAE5B,cAAK,SAAS,EAAC,OAAO,EAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE,YACvD,QAAQ,GACL,GACC,GACL,GACiB,CAC1B,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EAMR;IACC,MAAM,GAAG,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IACtC,OAAO,CACL,eACE,EAAE,EAAE,GAAG,CAAC,QAAQ,EAChB,SAAS,EAAE,CAAC,mBAAmB,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KACjE,IAAI,aAEP,QAAQ,EACT,iBACE,SAAS,EAAC,WAAW,EACrB,IAAI,EAAC,QAAQ,gBACF,cAAc,EACzB,OAAO,EAAE,GAAG,CAAC,KAAK,YAElB,KAAC,OAAO,IAAC,IAAI,EAAC,OAAO,EAAC,IAAI,EAAC,IAAI,GAAG,GAC3B,IACL,CACP,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAC/B,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EAMR;IACC,OAAO,CACL,cACE,SAAS,EAAE,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAClE,IAAI,YAEP,QAAQ,GACL,CACP,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EAMR;IACC,OAAO,CACL,cACE,SAAS,EAAE,CAAC,mBAAmB,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KACjE,IAAI,YAEP,QAAQ,GACL,CACP,CAAC;AACJ,CAAC","sourcesContent":["import {\n useEffect,\n useRef,\n useId,\n createContext,\n useContext,\n ReactNode,\n HTMLAttributes,\n MouseEvent,\n} from 'react';\nimport type { AtlDrawerSpec } from '../spec';\nimport './atl-drawer.css';\nimport { AtlIcon } from '../icon/atl-icon';\n\ninterface DrawerContextValue {\n headerId: string;\n close: () => void;\n}\n\nconst DrawerContext = createContext<DrawerContextValue>({\n headerId: '',\n close: () => undefined,\n});\n\n/**\n * Properties for the AtlDrawer component.\n */\nexport interface AtlDrawerProps extends AtlDrawerSpec {\n /**\n * Whether the drawer is open.\n */\n open?: boolean;\n /**\n * Callback triggered when the open state changes.\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * The position of the drawer on the screen.\n */\n position?: 'left' | 'right' | 'top' | 'bottom';\n /**\n * The size of the drawer.\n */\n size?: 'sm' | 'md' | 'lg' | 'full';\n /**\n * Whether to close the drawer when clicking on the backdrop.\n */\n closeOnBackdrop?: boolean;\n /**\n * The content of the drawer.\n */\n children?: ReactNode;\n}\n\n/**\n * A drawer component that slides in from the edge of the screen.\n */\nexport function AtlDrawer({\n open = false,\n onOpenChange,\n position = 'right',\n size = 'md',\n closeOnBackdrop = true,\n children,\n}: AtlDrawerProps) {\n const dialogRef = useRef<HTMLDialogElement>(null);\n const headerId = useId();\n const triggerElRef = useRef<Element | null>(null);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n if (open) {\n triggerElRef.current = document.activeElement;\n if (!dialog.open) dialog.showModal();\n } else {\n if (dialog.open) dialog.close();\n (triggerElRef.current as HTMLElement | null)?.focus();\n triggerElRef.current = null;\n }\n }, [open]);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n const onClose = () => onOpenChange?.(false);\n const onCancel = (e: Event) => {\n e.preventDefault();\n onOpenChange?.(false);\n };\n dialog.addEventListener('close', onClose);\n dialog.addEventListener('cancel', onCancel);\n return () => {\n dialog.removeEventListener('close', onClose);\n dialog.removeEventListener('cancel', onCancel);\n };\n }, [onOpenChange]);\n\n const handleBackdropClick = (e: MouseEvent<HTMLDialogElement>) => {\n if (!closeOnBackdrop) return;\n if (e.target === dialogRef.current) {\n onOpenChange?.(false);\n }\n };\n\n const hostClass = [\n 'atl-drawer-host',\n `position-${position}`,\n `size-${size}`,\n open && 'is-open',\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <DrawerContext.Provider value={{ headerId, close: () => onOpenChange?.(false) }}>\n <div className={hostClass}>\n <dialog\n ref={dialogRef}\n aria-labelledby={headerId}\n aria-modal=\"true\"\n onClick={handleBackdropClick}\n >\n <div className=\"panel\" onClick={(e) => e.stopPropagation()}>\n {children}\n </div>\n </dialog>\n </div>\n </DrawerContext.Provider>\n );\n}\n\n/**\n * The header component for an AtlDrawer.\n */\nexport function AtlDrawerHeader({\n children,\n className,\n ...rest\n}: HTMLAttributes<HTMLDivElement> & {\n /**\n * The content of the drawer header.\n */\n children?: ReactNode;\n}) {\n const ctx = useContext(DrawerContext);\n return (\n <div\n id={ctx.headerId}\n className={['atl-drawer-header', className].filter(Boolean).join(' ')}\n {...rest}\n >\n {children}\n <button\n className=\"close-btn\"\n type=\"button\"\n aria-label=\"Close drawer\"\n onClick={ctx.close}\n >\n <AtlIcon name=\"close\" size=\"sm\" />\n </button>\n </div>\n );\n}\n\n/**\n * The main content component for an AtlDrawer.\n */\nexport function AtlDrawerContent({\n children,\n className,\n ...rest\n}: HTMLAttributes<HTMLDivElement> & {\n /**\n * The main content of the drawer.\n */\n children?: ReactNode;\n}) {\n return (\n <div\n className={['atl-drawer-content', className].filter(Boolean).join(' ')}\n {...rest}\n >\n {children}\n </div>\n );\n}\n\n/**\n * The footer component for an AtlDrawer.\n */\nexport function AtlDrawerFooter({\n children,\n className,\n ...rest\n}: HTMLAttributes<HTMLDivElement> & {\n /**\n * The content of the drawer footer.\n */\n children?: ReactNode;\n}) {\n return (\n <div\n className={['atl-drawer-footer', className].filter(Boolean).join(' ')}\n {...rest}\n >\n {children}\n </div>\n );\n}\n"]}
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/* Geometry contract: every size this component states is a border-box size.
|
|
2
|
+
* Declared with the component rather than as a global reset, so it ships in the
|
|
3
|
+
* same file as the sizes it governs and no consuming app has to supply one.
|
|
4
|
+
* Gated by check:box-sizing; the resulting boxes are measured by check:geometry.
|
|
5
|
+
* See ADR-0043. */
|
|
6
|
+
.atl-icon,
|
|
7
|
+
.atl-icon * {
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
}
|
|
10
|
+
|
|
1
11
|
.atl-icon {
|
|
2
12
|
display: inline-flex;
|
|
3
13
|
align-items: center;
|
|
@@ -27,3 +37,11 @@
|
|
|
27
37
|
height: 1.5rem;
|
|
28
38
|
font-size: var(--ui-font-size-lg);
|
|
29
39
|
}
|
|
40
|
+
|
|
41
|
+
/* The size classes define the box; the svg fills it. Geometry is always the
|
|
42
|
+
* 0 0 24 24 viewBox, so every size is the same shape at a different scale. */
|
|
43
|
+
.atl-icon svg {
|
|
44
|
+
width: 100%;
|
|
45
|
+
height: 100%;
|
|
46
|
+
display: block;
|
|
47
|
+
}
|
|
@@ -16,7 +16,8 @@ export interface AtlIconProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'ari
|
|
|
16
16
|
label?: string;
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
19
|
+
* Vector icon. 23 named variants, drawn from the geometry in `icons.ts` so the
|
|
20
|
+
* same shape is used everywhere it appears. Matches the Figma `AtlIcon`
|
|
20
21
|
* component set. Decorative by default; pass `label` to announce a meaning
|
|
21
22
|
* to assistive tech.
|
|
22
23
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atl-icon.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/icon/atl-icon.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"atl-icon.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/icon/atl-icon.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAErE,OAAO,gBAAgB,CAAC;AAGxB;;GAEG;AACH,MAAM,WAAW,YACf,SAAQ,IAAI,CAAC,cAAc,CAAC,eAAe,CAAC,EAAE,YAAY,CAAC,EACzD,WAAW;IACb,qBAAqB;IACrB,IAAI,EAAE,WAAW,CAAC;IAClB,qBAAqB;IACrB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,EACtB,IAAI,EACJ,IAAW,EACX,KAAK,EACL,SAAS,EACT,GAAG,IAAI,EACR,EAAE,YAAY,+BAyBd"}
|
package/src/lib/icon/atl-icon.js
CHANGED
|
@@ -1,30 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { ATL_ICON_GEOMETRY, ATL_ICON_STROKE_WIDTH, ATL_ICON_VIEWBOX } from '../icons';
|
|
2
3
|
import './atl-icon.css';
|
|
3
|
-
const ICON_GLYPHS = {
|
|
4
|
-
success: '✓',
|
|
5
|
-
warning: '⚠',
|
|
6
|
-
danger: '✕',
|
|
7
|
-
info: 'ℹ',
|
|
8
|
-
error: '!',
|
|
9
|
-
'chevron-up': '▲',
|
|
10
|
-
'chevron-down': '▼',
|
|
11
|
-
'chevron-left': '‹',
|
|
12
|
-
'chevron-right': '›',
|
|
13
|
-
'sort-asc': '↑',
|
|
14
|
-
'sort-desc': '↓',
|
|
15
|
-
'arrow-right': '→',
|
|
16
|
-
'arrow-left': '←',
|
|
17
|
-
copy: '⎘',
|
|
18
|
-
paste: '⎗',
|
|
19
|
-
add: '⊕',
|
|
20
|
-
edit: '✏',
|
|
21
|
-
delete: '🗑',
|
|
22
|
-
close: '×',
|
|
23
|
-
more: '…',
|
|
24
|
-
'default-toast': '💬',
|
|
25
|
-
};
|
|
26
4
|
/**
|
|
27
|
-
*
|
|
5
|
+
* Vector icon. 23 named variants, drawn from the geometry in `icons.ts` so the
|
|
6
|
+
* same shape is used everywhere it appears. Matches the Figma `AtlIcon`
|
|
28
7
|
* component set. Decorative by default; pass `label` to announce a meaning
|
|
29
8
|
* to assistive tech.
|
|
30
9
|
*/
|
|
@@ -33,6 +12,8 @@ export function AtlIcon({ name, size = 'md', label, className, ...rest }) {
|
|
|
33
12
|
const accessibilityProps = label
|
|
34
13
|
? { role: 'img', 'aria-label': label }
|
|
35
14
|
: { 'aria-hidden': true };
|
|
36
|
-
|
|
15
|
+
const geometry = ATL_ICON_GEOMETRY[name];
|
|
16
|
+
const stroke = geometry.kind === 'stroke';
|
|
17
|
+
return (_jsx("span", { className: classes, ...accessibilityProps, ...rest, children: _jsx("svg", { viewBox: ATL_ICON_VIEWBOX, fill: stroke ? 'none' : 'currentColor', stroke: stroke ? 'currentColor' : undefined, strokeWidth: stroke ? ATL_ICON_STROKE_WIDTH : undefined, strokeLinecap: stroke ? 'round' : undefined, strokeLinejoin: stroke ? 'round' : undefined, "aria-hidden": "true", focusable: "false", children: geometry.paths.map((d) => (_jsx("path", { d: d }, d))) }) }));
|
|
37
18
|
}
|
|
38
19
|
//# sourceMappingURL=atl-icon.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atl-icon.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/icon/atl-icon.tsx"],"names":[],"mappings":";AAEA,OAAO,gBAAgB,
|
|
1
|
+
{"version":3,"file":"atl-icon.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/icon/atl-icon.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACtF,OAAO,gBAAgB,CAAC;AAoBxB;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,EACtB,IAAI,EACJ,IAAI,GAAG,IAAI,EACX,KAAK,EACL,SAAS,EACT,GAAG,IAAI,EACM;IACb,MAAM,OAAO,GAAG,CAAC,UAAU,EAAE,QAAQ,IAAI,EAAE,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClF,MAAM,kBAAkB,GAAG,KAAK;QAC9B,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE;QACtC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAa,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC;IAC1C,OAAO,CACL,eAAM,SAAS,EAAE,OAAO,KAAM,kBAAkB,KAAM,IAAI,YACxD,cACE,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,EACtC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,EAC3C,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,SAAS,EACvD,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAC3C,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,iBAChC,MAAM,EAClB,SAAS,EAAC,OAAO,YAEhB,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACzB,eAAc,CAAC,EAAE,CAAC,IAAP,CAAC,CAAU,CACvB,CAAC,GACE,GACD,CACR,CAAC;AACJ,CAAC","sourcesContent":["import { HTMLAttributes } from 'react';\nimport type { AtlIconName, AtlIconSize, AtlIconSpec } from '../spec';\nimport { ATL_ICON_GEOMETRY, ATL_ICON_STROKE_WIDTH, ATL_ICON_VIEWBOX } from '../icons';\nimport './atl-icon.css';\n\n\n/**\n * Properties for the AtlIcon component.\n */\nexport interface AtlIconProps\n extends Omit<HTMLAttributes<HTMLSpanElement>, 'aria-label'>,\n AtlIconSpec {\n /** The icon name. */\n name: AtlIconName;\n /** The icon size. */\n size?: AtlIconSize;\n /**\n * Accessible label. When provided, the icon is announced as an image with\n * this label. When omitted, the icon is hidden from assistive tech.\n */\n label?: string;\n}\n\n/**\n * Vector icon. 23 named variants, drawn from the geometry in `icons.ts` so the\n * same shape is used everywhere it appears. Matches the Figma `AtlIcon`\n * component set. Decorative by default; pass `label` to announce a meaning\n * to assistive tech.\n */\nexport function AtlIcon({\n name,\n size = 'md',\n label,\n className,\n ...rest\n}: AtlIconProps) {\n const classes = ['atl-icon', `size-${size}`, className].filter(Boolean).join(' ');\n const accessibilityProps = label\n ? { role: 'img', 'aria-label': label }\n : { 'aria-hidden': true as const };\n const geometry = ATL_ICON_GEOMETRY[name];\n const stroke = geometry.kind === 'stroke';\n return (\n <span className={classes} {...accessibilityProps} {...rest}>\n <svg\n viewBox={ATL_ICON_VIEWBOX}\n fill={stroke ? 'none' : 'currentColor'}\n stroke={stroke ? 'currentColor' : undefined}\n strokeWidth={stroke ? ATL_ICON_STROKE_WIDTH : undefined}\n strokeLinecap={stroke ? 'round' : undefined}\n strokeLinejoin={stroke ? 'round' : undefined}\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n {geometry.paths.map((d) => (\n <path key={d} d={d} />\n ))}\n </svg>\n </span>\n );\n}\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Icon geometry — the single source of truth for what every AtlIcon draws.
|
|
3
|
+
*
|
|
4
|
+
* Before this file, the library had four ways to draw the same thing: AtlIcon
|
|
5
|
+
* rendered Unicode glyphs and no component used it; eleven components drew 14
|
|
6
|
+
* inline `<svg>`s of their own; and two stylesheets put a literal `✕` in a CSS
|
|
7
|
+
* `content:`. The result was one concept with several drawings — `close` existed
|
|
8
|
+
* as an identical two-line SVG in five components, as a *differently drawn* X in
|
|
9
|
+
* AtlStepper, as `'×'` in AtlIcon and as `'✕'` in CSS, and `check` existed as
|
|
10
|
+
* three unrelated paths. Nothing gated it. See ADR-0046.
|
|
11
|
+
*
|
|
12
|
+
* Conventions, which every entry follows so a consumer can scale and colour icons
|
|
13
|
+
* without knowing which one they got:
|
|
14
|
+
*
|
|
15
|
+
* - **One viewBox: `0 0 24 24`.** Rendered size comes from the `size` prop, never
|
|
16
|
+
* from the geometry, so `sm`/`md`/`lg` are the same shape at three scales.
|
|
17
|
+
* - **`stroke` icons** are drawn with `currentColor`, `stroke-width: 2`, round caps
|
|
18
|
+
* and joins, and no fill. **`fill` icons** are solid `currentColor` silhouettes.
|
|
19
|
+
* Mixing the two inside one icon is not allowed — it reads wrong at small sizes.
|
|
20
|
+
* - **Paths only** (no `<line>`/`<rect>`/`<polyline>`), so the renderer in each
|
|
21
|
+
* framework is a single `<path>` loop rather than a per-primitive switch.
|
|
22
|
+
*
|
|
23
|
+
* The seven icons the library itself uses (`close`, `check`, `chevron-down`,
|
|
24
|
+
* `copy`, `person`, `sort-asc`, `sort-desc`) keep the geometry the components
|
|
25
|
+
* already shipped, normalised to the 24 viewBox. The rest are the same idiom.
|
|
26
|
+
*/
|
|
27
|
+
export type AtlIconKind = 'stroke' | 'fill';
|
|
28
|
+
export interface AtlIconGeometry {
|
|
29
|
+
/** How the paths are painted. Never mixed within one icon. */
|
|
30
|
+
kind: AtlIconKind;
|
|
31
|
+
/** Path `d` values, drawn in order, all in the 0 0 24 24 viewBox. */
|
|
32
|
+
paths: string[];
|
|
33
|
+
}
|
|
34
|
+
/** viewBox shared by every icon. */
|
|
35
|
+
export declare const ATL_ICON_VIEWBOX = "0 0 24 24";
|
|
36
|
+
/** Stroke width for `kind: 'stroke'` icons, in viewBox units. */
|
|
37
|
+
export declare const ATL_ICON_STROKE_WIDTH = 2;
|
|
38
|
+
export declare const ATL_ICON_GEOMETRY: Record<string, AtlIconGeometry>;
|
|
39
|
+
//# sourceMappingURL=icons.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../../../../libs/react/src/lib/icons.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE5C,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,IAAI,EAAE,WAAW,CAAC;IAClB,qEAAqE;IACrE,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,oCAAoC;AACpC,eAAO,MAAM,gBAAgB,cAAc,CAAC;AAE5C,iEAAiE;AACjE,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CA4C7D,CAAC"}
|
package/src/lib/icons.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// AUTO-GENERATED from libs/spec/src/icons.ts — do not edit here.
|
|
2
|
+
// Run `node tools/scripts/sync-spec.mjs` after editing the source of truth.
|
|
3
|
+
// The framework libs inline this so @atelier-ui/spec stays internal.
|
|
4
|
+
/** viewBox shared by every icon. */
|
|
5
|
+
export const ATL_ICON_VIEWBOX = '0 0 24 24';
|
|
6
|
+
/** Stroke width for `kind: 'stroke'` icons, in viewBox units. */
|
|
7
|
+
export const ATL_ICON_STROKE_WIDTH = 2;
|
|
8
|
+
export const ATL_ICON_GEOMETRY = {
|
|
9
|
+
// ── status ────────────────────────────────────────────────────────────────
|
|
10
|
+
// `success` is a status icon and sits beside the circled danger/error/info, so it
|
|
11
|
+
// is a circled check. `check` is the bare mark used inside controls (combobox
|
|
12
|
+
// option, stepper step, copy confirmation) — two names, two shapes, on purpose.
|
|
13
|
+
success: { kind: 'stroke', paths: ['M12 3A9 9 0 1 0 12 21A9 9 0 1 0 12 3', 'M8 12L11 15L16 9'] },
|
|
14
|
+
check: { kind: 'stroke', paths: ['M20 6L9 17L4 12'] },
|
|
15
|
+
warning: { kind: 'stroke', paths: ['M12 3L22 20H2L12 3Z', 'M12 9V14', 'M12 17.5V17.6'] },
|
|
16
|
+
danger: { kind: 'stroke', paths: ['M12 3A9 9 0 1 0 12 21A9 9 0 1 0 12 3', 'M15 9L9 15', 'M9 9L15 15'] },
|
|
17
|
+
error: { kind: 'stroke', paths: ['M12 3A9 9 0 1 0 12 21A9 9 0 1 0 12 3', 'M12 7V13', 'M12 16.5V16.6'] },
|
|
18
|
+
info: { kind: 'stroke', paths: ['M12 3A9 9 0 1 0 12 21A9 9 0 1 0 12 3', 'M12 11V17', 'M12 7.5V7.6'] },
|
|
19
|
+
// ── direction ─────────────────────────────────────────────────────────────
|
|
20
|
+
'chevron-up': { kind: 'stroke', paths: ['M6 15L12 9L18 15'] },
|
|
21
|
+
'chevron-down': { kind: 'stroke', paths: ['M6 9L12 15L18 9'] },
|
|
22
|
+
'chevron-left': { kind: 'stroke', paths: ['M15 6L9 12L15 18'] },
|
|
23
|
+
'chevron-right': { kind: 'stroke', paths: ['M9 6L15 12L9 18'] },
|
|
24
|
+
'arrow-left': { kind: 'stroke', paths: ['M19 12H5', 'M11 6L5 12L11 18'] },
|
|
25
|
+
'arrow-right': { kind: 'stroke', paths: ['M5 12H19', 'M13 6L19 12L13 18'] },
|
|
26
|
+
// ── sorting — two solid triangles, used separately by AtlTable ────────────
|
|
27
|
+
'sort-asc': { kind: 'fill', paths: ['M12 4L19 13H5L12 4Z'] },
|
|
28
|
+
'sort-desc': { kind: 'fill', paths: ['M12 20L5 11H19L12 20Z'] },
|
|
29
|
+
// ── actions ───────────────────────────────────────────────────────────────
|
|
30
|
+
close: { kind: 'stroke', paths: ['M18 6L6 18', 'M6 6L18 18'] },
|
|
31
|
+
add: { kind: 'stroke', paths: ['M12 5V19', 'M5 12H19'] },
|
|
32
|
+
more: { kind: 'fill', paths: ['M6 10A2 2 0 1 0 6 14A2 2 0 1 0 6 10', 'M12 10A2 2 0 1 0 12 14A2 2 0 1 0 12 10', 'M18 10A2 2 0 1 0 18 14A2 2 0 1 0 18 10'] },
|
|
33
|
+
copy: { kind: 'stroke', paths: ['M9 9H20V20H9V9Z', 'M15 5H4V16H5'] },
|
|
34
|
+
paste: { kind: 'stroke', paths: ['M8 4H16V7H8V4Z', 'M6 6H5V20H19V6H18'] },
|
|
35
|
+
edit: { kind: 'stroke', paths: ['M4 20H8L19 9L15 5L4 16V20Z', 'M14 6L18 10'] },
|
|
36
|
+
delete: { kind: 'stroke', paths: ['M4 7H20', 'M6 7V20H18V7', 'M10 4H14', 'M10 11V16', 'M14 11V16'] },
|
|
37
|
+
// ── content ───────────────────────────────────────────────────────────────
|
|
38
|
+
person: {
|
|
39
|
+
kind: 'fill',
|
|
40
|
+
paths: [
|
|
41
|
+
'M12 12c2.761 0 5-2.239 5-5s-2.239-5-5-5-5 2.239-5 5 2.239 5 5 5zm0 2c-3.314 0-10 1.343-10 4v2h20v-2c0-2.657-6.686-4-10-4z',
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
'default-toast': {
|
|
45
|
+
kind: 'stroke',
|
|
46
|
+
paths: ['M4 5H20V16H13L8 20V16H4V5Z'],
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=icons.js.map
|