@protonradio/proton-ui 0.12.0 → 0.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ButtonGroup/ButtonGroup.cjs.js +1 -1
- package/dist/components/ButtonGroup/ButtonGroup.cjs.js.map +1 -1
- package/dist/components/ButtonGroup/ButtonGroup.es.js +30 -16
- package/dist/components/ButtonGroup/ButtonGroup.es.js.map +1 -1
- package/dist/components/Checkbox/CheckboxInput/CheckboxInput.cjs.js +1 -1
- package/dist/components/Checkbox/CheckboxInput/CheckboxInput.cjs.js.map +1 -1
- package/dist/components/Checkbox/CheckboxInput/CheckboxInput.es.js +48 -48
- package/dist/components/Checkbox/CheckboxInput/CheckboxInput.es.js.map +1 -1
- package/dist/components/Checkbox/CheckboxRadioGroup/CheckboxRadioGroup.cjs.js +1 -1
- package/dist/components/Checkbox/CheckboxRadioGroup/CheckboxRadioGroup.cjs.js.map +1 -1
- package/dist/components/Checkbox/CheckboxRadioGroup/CheckboxRadioGroup.es.js +43 -43
- package/dist/components/Checkbox/CheckboxRadioGroup/CheckboxRadioGroup.es.js.map +1 -1
- package/dist/components/Input/BaseInput/Input.cjs.js +1 -1
- package/dist/components/Input/BaseInput/Input.cjs.js.map +1 -1
- package/dist/components/Input/BaseInput/Input.es.js +62 -62
- package/dist/components/Input/BaseInput/Input.es.js.map +1 -1
- package/dist/components/Popover/Popover.cjs.js.map +1 -1
- package/dist/components/Popover/Popover.es.js.map +1 -1
- package/dist/components/Select/Select.cjs.js +1 -1
- package/dist/components/Select/Select.cjs.js.map +1 -1
- package/dist/components/Select/Select.es.js +40 -29
- package/dist/components/Select/Select.es.js.map +1 -1
- package/dist/components/Switch/Switch.cjs.js +1 -1
- package/dist/components/Switch/Switch.cjs.js.map +1 -1
- package/dist/components/Switch/Switch.es.js +27 -26
- package/dist/components/Switch/Switch.es.js.map +1 -1
- package/dist/components/Table/DataTable/DataTable.cjs.js +1 -1
- package/dist/components/Table/DataTable/DataTable.cjs.js.map +1 -1
- package/dist/components/Table/DataTable/DataTable.es.js +6 -6
- package/dist/components/Table/DataTable/DataTable.es.js.map +1 -1
- package/dist/components/Tooltip/ResponsiveTooltip.cjs.js.map +1 -1
- package/dist/components/Tooltip/ResponsiveTooltip.es.js.map +1 -1
- package/dist/components/Tooltip/Tooltip.cjs.js.map +1 -1
- package/dist/components/Tooltip/Tooltip.es.js.map +1 -1
- package/dist/constants.d.ts +6 -0
- package/dist/design/darkTheme/colors.cjs.js +1 -1
- package/dist/design/darkTheme/colors.cjs.js.map +1 -1
- package/dist/design/darkTheme/colors.es.js +14 -14
- package/dist/design/darkTheme/colors.es.js.map +1 -1
- package/dist/index.d.ts +20 -14
- package/dist/style.css +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.cjs.js","sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n forwardRef,\n ReactNode,\n useEffect,\n useRef,\n useState,\n type ForwardedRef,\n type CSSProperties,\n} from \"react\";\nimport { Select as RadixSelect } from \"radix-ui\";\nimport { useTheme } from \"../ThemeProvider\";\nimport { useBreakpoint } from \"../../hooks/useBreakpoint\";\nimport { BREAKPOINTS } from \"../../constants\";\nimport { csx } from \"../../utils\";\n\nimport { ActionMenu, type ActionMenuAction } from \"../ActionMenu/ActionMenu\";\nimport { CaretDown as CaretDownIcon } from \"../Icon\";\n\nimport \"./Select.css\";\nimport \"../Menu/Menu.css\";\nimport \"../Elevation/Elevation.css\";\n\ninterface SelectButtonProps {\n disabled?: boolean;\n isOpen?: boolean;\n selectedItem?: SelectItem;\n onClick?: () => void;\n isRounded?: boolean;\n \"data-testid\"?: string;\n}\n\nconst SelectButton = forwardRef<HTMLButtonElement, SelectButtonProps>(\n (\n { disabled, isOpen, onClick, isRounded, selectedItem, \"data-testid\": testId },\n ref: ForwardedRef<HTMLButtonElement>,\n ) => {\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"combobox\"\n aria-expanded={isOpen}\n aria-autocomplete=\"none\"\n data-state={isOpen ? \"open\" : \"closed\"}\n data-testid={testId}\n disabled={disabled}\n onClick={onClick}\n className={csx(\n \"proton-Select__trigger\",\n \"proton-Elevation--glass\",\n disabled && \"proton-Select__trigger--disabled\",\n !isOpen && \"proton-Select__trigger--closed\",\n isOpen && \"proton-Select__trigger--opened\",\n isRounded && \"proton-Select__trigger--rounded\",\n )}\n >\n <span className=\"proton-Select__value\">\n {selectedItem ? selectedItem.label : \"Select an option\"}\n </span>\n <span\n className={csx(\n \"proton-Select__trigger_icon\",\n isOpen && \"proton-Select__trigger_icon--flipped\",\n )}\n >\n <CaretDownIcon size={16} />\n </span>\n </button>\n );\n },\n);\n\nSelectButton.displayName = \"ProtonUISelectButton\";\n\nexport interface SelectItem {\n /** The label to display for the item */\n label: string;\n\n /** The key of the item */\n key: string;\n\n /** The URL to navigate to when the item is clicked, turns item into an a tag */\n to?: string;\n}\n\nexport interface SelectProps {\n /** Array of keys that should be disabled\n * @example [\"Thing 1\", \"Thing 2\"]\n */\n disabledKeys?: string[];\n\n /** The key of the default selected item */\n defaultSelectedKey?: string;\n\n /** Test ID for the select */\n \"data-testid\"?: string;\n\n /** Whether the select is disabled */\n isDisabled?: boolean;\n\n /** Array of items to display\n * @example [{ key: \"thing-1\", label: \"Thing 1\" }, { key: \"thing-2\", label: \"Thing 2\" }]\n * @see {@link SelectItem}\n */\n items: SelectItem[];\n\n /** Whether the select button is rounded\n * @default false\n */\n isRounded?: boolean;\n\n /** Label to display above the select\n * @external https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#text\n */\n label?: string;\n\n /** The name of the select field */\n name: string;\n\n /** Callback fired when the menu closes */\n onClose?: () => void;\n\n /** Callback fired when the menu opens */\n onOpen?: () => void;\n\n /** Callback fired when selection changes */\n onSelectionChange?: (key: string) => void;\n\n /** Currently selected key */\n selectedKey?: string;\n}\n\n/**\n * A dropdown select menu that opens a popover on desktop and an action menu on mobile/touch devices.\n * Supports controlled and uncontrolled modes.\n *\n * API:\n * - {@link SelectProps}\n */\nexport function Select({\n label,\n name,\n isDisabled,\n disabledKeys,\n selectedKey,\n onSelectionChange,\n defaultSelectedKey,\n onOpen,\n onClose,\n items,\n isRounded = false,\n \"data-testid\": testId,\n}: SelectProps) {\n const [isOpen, setIsOpen] = useState(false);\n const isControlled = selectedKey !== undefined;\n const [internalSelectedKey, setInternalSelectedKey] = useState(\n defaultSelectedKey ?? \"\",\n );\n const { className: themeClass, style: themeStyle } = useTheme();\n const isMobile = useBreakpoint(BREAKPOINTS.MEDIUM);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const hiddenInputRef = useRef<HTMLInputElement>(null);\n\n // Handle controlled vs uncontrolled state\n const currentSelectedKey = isControlled\n ? (selectedKey as string)\n : internalSelectedKey;\n const selectedItem = items.find((item) => item.key === currentSelectedKey);\n\n const handleValueChange = (value: string) => {\n if (!isControlled) {\n setInternalSelectedKey(value);\n }\n onSelectionChange?.(value);\n\n // Update hidden input for form submission\n if (hiddenInputRef.current) {\n hiddenInputRef.current.value = value;\n hiddenInputRef.current.dispatchEvent(\n new Event(\"change\", { bubbles: true }),\n );\n }\n };\n\n const handleOpenChange = (open: boolean) => {\n setIsOpen(open);\n if (open) {\n onOpen?.();\n } else {\n onClose?.();\n }\n };\n\n // Update internal state when controlled selectedKey changes\n useEffect(() => {\n if (isControlled) {\n setInternalSelectedKey(selectedKey);\n }\n }, [isControlled]);\n\n const actionItems: ActionMenuAction[] = items.map((item) => ({\n key: item.key,\n label: item.label,\n to: item.to,\n onAction: () => {\n handleValueChange(item.key);\n setIsOpen(false);\n },\n }));\n\n if (isMobile) {\n return (\n <div\n className=\"proton-Select\"\n aria-label={label || name}\n aria-disabled={isDisabled}\n >\n {label && (\n <div className=\"proton-Select__label\" data-testid=\"select-label\">\n {label}\n </div>\n )}\n\n {/* Hidden input for form submission */}\n <input\n ref={hiddenInputRef}\n type=\"hidden\"\n name={name}\n value={currentSelectedKey}\n data-testid=\"hidden-select-container\"\n />\n\n <SelectButton\n isOpen={isOpen}\n isRounded={isRounded}\n ref={triggerRef}\n disabled={isDisabled}\n data-testid={testId}\n onClick={() => setIsOpen(true)}\n selectedItem={selectedItem}\n />\n\n <ActionMenu\n isOpen={isOpen}\n onClose={() => setIsOpen(false)}\n actions={actionItems}\n selectedKeys={[currentSelectedKey]}\n disabledKeys={disabledKeys}\n />\n </div>\n );\n }\n\n return (\n <div\n className=\"proton-Select\"\n aria-label={label || name}\n aria-disabled={isDisabled}\n >\n {label && (\n <div className=\"proton-Select__label\" data-testid=\"select-label\">\n {label}\n </div>\n )}\n\n {/* Hidden input for form submission */}\n <input\n ref={hiddenInputRef}\n type=\"hidden\"\n name={name}\n value={currentSelectedKey}\n data-testid=\"hidden-select-container\"\n />\n\n <RadixSelect.Root\n value={currentSelectedKey}\n onValueChange={handleValueChange}\n onOpenChange={handleOpenChange}\n disabled={isDisabled}\n >\n <RadixSelect.Trigger asChild>\n <SelectButton\n isRounded={isRounded}\n isOpen={isOpen}\n ref={triggerRef}\n disabled={isDisabled}\n data-testid={testId}\n selectedItem={selectedItem}\n />\n </RadixSelect.Trigger>\n\n <RadixSelect.Portal>\n <RadixSelect.Content\n className={csx(\n \"proton-Menu\",\n \"proton-MenuTrigger__menu\",\n \"proton-Elevation--glass\",\n themeClass,\n )}\n style={themeStyle as CSSProperties}\n position=\"popper\"\n >\n <RadixSelect.Viewport>\n {items.map((item) => (\n <RadixSelect.Item\n key={item.key}\n value={item.key}\n disabled={disabledKeys?.includes(item.key)}\n className=\"proton-Menu__item\"\n >\n <RadixSelect.ItemText>{item.label}</RadixSelect.ItemText>\n </RadixSelect.Item>\n ))}\n </RadixSelect.Viewport>\n </RadixSelect.Content>\n </RadixSelect.Portal>\n </RadixSelect.Root>\n </div>\n );\n}\n\nSelect.displayName = \"ProtonUISelect\";\n"],"names":["SelectButton","forwardRef","disabled","isOpen","onClick","isRounded","selectedItem","testId","ref","jsxs","csx","jsx","CaretDownIcon","Select","label","name","isDisabled","disabledKeys","selectedKey","onSelectionChange","defaultSelectedKey","onOpen","onClose","items","setIsOpen","useState","isControlled","internalSelectedKey","setInternalSelectedKey","themeClass","themeStyle","useTheme","isMobile","useBreakpoint","BREAKPOINTS","triggerRef","useRef","hiddenInputRef","currentSelectedKey","item","handleValueChange","value","handleOpenChange","open","useEffect","actionItems","ActionMenu","RadixSelect"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Select.cjs.js","sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n forwardRef,\n ReactNode,\n useEffect,\n useRef,\n useState,\n type ForwardedRef,\n type CSSProperties,\n} from \"react\";\nimport { Select as RadixSelect } from \"radix-ui\";\nimport { useTheme } from \"../ThemeProvider\";\nimport { useBreakpoint } from \"../../hooks/useBreakpoint\";\nimport { BREAKPOINTS } from \"../../constants\";\nimport { csx } from \"../../utils\";\n\nimport { ActionMenu, type ActionMenuAction } from \"../ActionMenu/ActionMenu\";\nimport { CaretDown as CaretDownIcon } from \"../Icon\";\n\nimport \"./Select.css\";\nimport \"../Menu/Menu.css\";\nimport \"../Elevation/Elevation.css\";\n\ninterface SelectButtonProps {\n disabled?: boolean;\n isOpen?: boolean;\n selectedItem?: SelectItem;\n onClick?: () => void;\n isRounded?: boolean;\n ariaLabel?: string;\n \"data-testid\"?: string;\n}\n\nconst SelectButton = forwardRef<HTMLButtonElement, SelectButtonProps>(\n (\n {\n disabled,\n isOpen,\n onClick,\n isRounded,\n selectedItem,\n ariaLabel,\n \"data-testid\": testId,\n },\n ref: ForwardedRef<HTMLButtonElement>,\n ) => {\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"combobox\"\n aria-label={ariaLabel}\n aria-expanded={isOpen}\n aria-autocomplete=\"none\"\n data-state={isOpen ? \"open\" : \"closed\"}\n data-testid={testId}\n disabled={disabled}\n onClick={onClick}\n className={csx(\n \"proton-Select__trigger\",\n \"proton-Elevation--glass\",\n disabled && \"proton-Select__trigger--disabled\",\n !isOpen && \"proton-Select__trigger--closed\",\n isOpen && \"proton-Select__trigger--opened\",\n isRounded && \"proton-Select__trigger--rounded\",\n )}\n >\n <span className=\"proton-Select__value\">\n {selectedItem ? selectedItem.label : \"Select an option\"}\n </span>\n <span\n className={csx(\n \"proton-Select__trigger_icon\",\n isOpen && \"proton-Select__trigger_icon--flipped\",\n )}\n >\n <CaretDownIcon size={16} />\n </span>\n </button>\n );\n },\n);\n\nSelectButton.displayName = \"ProtonUISelectButton\";\n\nexport interface SelectItem {\n /** The label to display for the item */\n label: string;\n\n /** The key of the item */\n key: string;\n\n /** The URL to navigate to when the item is clicked, turns item into an a tag */\n to?: string;\n}\n\nexport interface SelectProps {\n /** Array of keys that should be disabled\n * @example [\"Thing 1\", \"Thing 2\"]\n */\n disabledKeys?: string[];\n\n /** The key of the default selected item */\n defaultSelectedKey?: string;\n\n /** Test ID for the select */\n \"data-testid\"?: string;\n\n /** Whether the select is disabled */\n isDisabled?: boolean;\n\n /** Array of items to display\n * @example [{ key: \"thing-1\", label: \"Thing 1\" }, { key: \"thing-2\", label: \"Thing 2\" }]\n * @see {@link SelectItem}\n */\n items: SelectItem[];\n\n /** Whether the select button is rounded\n * @default false\n */\n isRounded?: boolean;\n\n /** Label to display above the select\n * @external https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#text\n */\n label?: string;\n\n /** The name of the select field */\n name: string;\n\n /** Callback fired when the menu closes */\n onClose?: () => void;\n\n /** Callback fired when the menu opens */\n onOpen?: () => void;\n\n /** Callback fired when selection changes */\n onSelectionChange?: (key: string) => void;\n\n /** Currently selected key */\n selectedKey?: string;\n}\n\n/**\n * A dropdown select menu that opens a popover on desktop and an action menu on mobile/touch devices.\n * Supports controlled and uncontrolled modes.\n *\n * API:\n * - {@link SelectProps}\n */\nexport function Select({\n label,\n name,\n isDisabled,\n disabledKeys,\n selectedKey,\n onSelectionChange,\n defaultSelectedKey,\n onOpen,\n onClose,\n items,\n isRounded = false,\n \"data-testid\": testId,\n}: SelectProps) {\n const [isOpen, setIsOpen] = useState(false);\n const isControlled = selectedKey !== undefined;\n const [internalSelectedKey, setInternalSelectedKey] = useState(\n defaultSelectedKey ?? \"\",\n );\n const { className: themeClass, style: themeStyle } = useTheme();\n const isMobile = useBreakpoint(BREAKPOINTS.MEDIUM);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const hiddenInputRef = useRef<HTMLInputElement>(null);\n\n // Handle controlled vs uncontrolled state\n const currentSelectedKey = isControlled\n ? (selectedKey as string)\n : internalSelectedKey;\n const selectedItem = items.find((item) => item.key === currentSelectedKey);\n\n const handleValueChange = (value: string) => {\n if (!isControlled) {\n setInternalSelectedKey(value);\n }\n onSelectionChange?.(value);\n\n // Update hidden input for form submission\n if (hiddenInputRef.current) {\n hiddenInputRef.current.value = value;\n hiddenInputRef.current.dispatchEvent(\n new Event(\"change\", { bubbles: true }),\n );\n }\n };\n\n const handleOpenChange = (open: boolean) => {\n setIsOpen(open);\n if (open) {\n onOpen?.();\n } else {\n onClose?.();\n }\n };\n\n // Update internal state when controlled selectedKey changes\n useEffect(() => {\n if (isControlled) {\n setInternalSelectedKey(selectedKey);\n }\n }, [isControlled]);\n\n const actionItems: ActionMenuAction[] = items.map((item) => ({\n key: item.key,\n label: item.label,\n to: item.to,\n onAction: () => {\n handleValueChange(item.key);\n setIsOpen(false);\n },\n }));\n\n if (isMobile) {\n return (\n <div\n className=\"proton-Select\"\n aria-label={label || name}\n aria-disabled={isDisabled}\n >\n {label && (\n <div className=\"proton-Select__label\" data-testid=\"select-label\">\n {label}\n </div>\n )}\n\n {/* Hidden input for form submission */}\n <input\n ref={hiddenInputRef}\n type=\"hidden\"\n name={name}\n value={currentSelectedKey}\n data-testid=\"hidden-select-container\"\n />\n\n <SelectButton\n isOpen={isOpen}\n isRounded={isRounded}\n ref={triggerRef}\n disabled={isDisabled}\n ariaLabel={label || name}\n data-testid={testId}\n onClick={() => setIsOpen(true)}\n selectedItem={selectedItem}\n />\n\n <ActionMenu\n isOpen={isOpen}\n onClose={() => setIsOpen(false)}\n actions={actionItems}\n selectedKeys={[currentSelectedKey]}\n disabledKeys={disabledKeys}\n />\n </div>\n );\n }\n\n return (\n <div\n className=\"proton-Select\"\n aria-label={label || name}\n aria-disabled={isDisabled}\n >\n {label && (\n <div className=\"proton-Select__label\" data-testid=\"select-label\">\n {label}\n </div>\n )}\n\n {/* Hidden input for form submission */}\n <input\n ref={hiddenInputRef}\n type=\"hidden\"\n name={name}\n value={currentSelectedKey}\n data-testid=\"hidden-select-container\"\n />\n\n <RadixSelect.Root\n value={currentSelectedKey}\n onValueChange={handleValueChange}\n onOpenChange={handleOpenChange}\n disabled={isDisabled}\n >\n <RadixSelect.Trigger asChild>\n <SelectButton\n isRounded={isRounded}\n isOpen={isOpen}\n ref={triggerRef}\n disabled={isDisabled}\n ariaLabel={label || name}\n data-testid={testId}\n selectedItem={selectedItem}\n />\n </RadixSelect.Trigger>\n\n <RadixSelect.Portal>\n <RadixSelect.Content\n className={csx(\n \"proton-Menu\",\n \"proton-MenuTrigger__menu\",\n \"proton-Elevation--glass\",\n themeClass,\n )}\n style={themeStyle as CSSProperties}\n position=\"popper\"\n >\n <RadixSelect.Viewport>\n {items.map((item) => (\n <RadixSelect.Item\n key={item.key}\n value={item.key}\n disabled={disabledKeys?.includes(item.key)}\n className=\"proton-Menu__item\"\n >\n <RadixSelect.ItemText>{item.label}</RadixSelect.ItemText>\n </RadixSelect.Item>\n ))}\n </RadixSelect.Viewport>\n </RadixSelect.Content>\n </RadixSelect.Portal>\n </RadixSelect.Root>\n </div>\n );\n}\n\nSelect.displayName = \"ProtonUISelect\";\n"],"names":["SelectButton","forwardRef","disabled","isOpen","onClick","isRounded","selectedItem","ariaLabel","testId","ref","jsxs","csx","jsx","CaretDownIcon","Select","label","name","isDisabled","disabledKeys","selectedKey","onSelectionChange","defaultSelectedKey","onOpen","onClose","items","setIsOpen","useState","isControlled","internalSelectedKey","setInternalSelectedKey","themeClass","themeStyle","useTheme","isMobile","useBreakpoint","BREAKPOINTS","triggerRef","useRef","hiddenInputRef","currentSelectedKey","item","handleValueChange","value","handleOpenChange","open","useEffect","actionItems","ActionMenu","RadixSelect"],"mappings":"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"}
|
|
@@ -3,24 +3,33 @@ import { useState as I, useRef as E, useEffect as A, forwardRef as C } from "rea
|
|
|
3
3
|
import { Select as n } from "radix-ui";
|
|
4
4
|
import { useTheme as U } from "../ThemeProvider.es.js";
|
|
5
5
|
import { useBreakpoint as V } from "../../hooks/useBreakpoint.es.js";
|
|
6
|
-
import { ActionMenu as
|
|
6
|
+
import { ActionMenu as L } from "../ActionMenu/ActionMenu.es.js";
|
|
7
7
|
/* empty css */
|
|
8
8
|
/* empty css */
|
|
9
9
|
/* empty css */
|
|
10
10
|
import { csx as g } from "../../utils/string.es.js";
|
|
11
|
-
import { BREAKPOINTS as
|
|
12
|
-
import { CaretDown as
|
|
11
|
+
import { BREAKPOINTS as z } from "../../constants/breakpoint.es.js";
|
|
12
|
+
import { CaretDown as $ } from "../Icon/IconComponents/CaretDown.es.js";
|
|
13
13
|
const j = C(
|
|
14
|
-
({
|
|
14
|
+
({
|
|
15
|
+
disabled: o,
|
|
16
|
+
isOpen: r,
|
|
17
|
+
onClick: a,
|
|
18
|
+
isRounded: l,
|
|
19
|
+
selectedItem: s,
|
|
20
|
+
ariaLabel: c,
|
|
21
|
+
"data-testid": f
|
|
22
|
+
}, i) => /* @__PURE__ */ e.jsxs(
|
|
15
23
|
"button",
|
|
16
24
|
{
|
|
17
|
-
ref:
|
|
25
|
+
ref: i,
|
|
18
26
|
type: "button",
|
|
19
27
|
role: "combobox",
|
|
28
|
+
"aria-label": c,
|
|
20
29
|
"aria-expanded": r,
|
|
21
30
|
"aria-autocomplete": "none",
|
|
22
31
|
"data-state": r ? "open" : "closed",
|
|
23
|
-
"data-testid":
|
|
32
|
+
"data-testid": f,
|
|
24
33
|
disabled: o,
|
|
25
34
|
onClick: a,
|
|
26
35
|
className: g(
|
|
@@ -40,7 +49,7 @@ const j = C(
|
|
|
40
49
|
"proton-Select__trigger_icon",
|
|
41
50
|
r && "proton-Select__trigger_icon--flipped"
|
|
42
51
|
),
|
|
43
|
-
children: /* @__PURE__ */ e.jsx(
|
|
52
|
+
children: /* @__PURE__ */ e.jsx($, { size: 16 })
|
|
44
53
|
}
|
|
45
54
|
)
|
|
46
55
|
]
|
|
@@ -48,38 +57,38 @@ const j = C(
|
|
|
48
57
|
)
|
|
49
58
|
);
|
|
50
59
|
j.displayName = "ProtonUISelectButton";
|
|
51
|
-
function
|
|
60
|
+
function q({
|
|
52
61
|
label: o,
|
|
53
62
|
name: r,
|
|
54
63
|
isDisabled: a,
|
|
55
64
|
disabledKeys: l,
|
|
56
65
|
selectedKey: s,
|
|
57
66
|
onSelectionChange: c,
|
|
58
|
-
defaultSelectedKey:
|
|
59
|
-
onOpen:
|
|
67
|
+
defaultSelectedKey: f,
|
|
68
|
+
onOpen: i,
|
|
60
69
|
onClose: h,
|
|
61
70
|
items: x,
|
|
62
71
|
isRounded: S = !1,
|
|
63
72
|
"data-testid": v
|
|
64
73
|
}) {
|
|
65
|
-
const [_,
|
|
66
|
-
|
|
67
|
-
), { className: R, style: T } = U(), w = V(
|
|
68
|
-
|
|
74
|
+
const [_, u] = I(!1), m = s !== void 0, [M, N] = I(
|
|
75
|
+
f ?? ""
|
|
76
|
+
), { className: R, style: T } = U(), w = V(z.MEDIUM), y = E(null), d = E(null), p = m ? s : M, b = x.find((t) => t.key === p), k = (t) => {
|
|
77
|
+
m || N(t), c == null || c(t), d.current && (d.current.value = t, d.current.dispatchEvent(
|
|
69
78
|
new Event("change", { bubbles: !0 })
|
|
70
79
|
));
|
|
71
80
|
}, B = (t) => {
|
|
72
|
-
|
|
81
|
+
u(t), t ? i == null || i() : h == null || h();
|
|
73
82
|
};
|
|
74
83
|
A(() => {
|
|
75
|
-
|
|
76
|
-
}, [
|
|
84
|
+
m && N(s);
|
|
85
|
+
}, [m]);
|
|
77
86
|
const P = x.map((t) => ({
|
|
78
87
|
key: t.key,
|
|
79
88
|
label: t.label,
|
|
80
89
|
to: t.to,
|
|
81
90
|
onAction: () => {
|
|
82
|
-
k(t.key),
|
|
91
|
+
k(t.key), u(!1);
|
|
83
92
|
}
|
|
84
93
|
}));
|
|
85
94
|
return w ? /* @__PURE__ */ e.jsxs(
|
|
@@ -93,10 +102,10 @@ function F({
|
|
|
93
102
|
/* @__PURE__ */ e.jsx(
|
|
94
103
|
"input",
|
|
95
104
|
{
|
|
96
|
-
ref:
|
|
105
|
+
ref: d,
|
|
97
106
|
type: "hidden",
|
|
98
107
|
name: r,
|
|
99
|
-
value:
|
|
108
|
+
value: p,
|
|
100
109
|
"data-testid": "hidden-select-container"
|
|
101
110
|
}
|
|
102
111
|
),
|
|
@@ -107,18 +116,19 @@ function F({
|
|
|
107
116
|
isRounded: S,
|
|
108
117
|
ref: y,
|
|
109
118
|
disabled: a,
|
|
119
|
+
ariaLabel: o || r,
|
|
110
120
|
"data-testid": v,
|
|
111
|
-
onClick: () =>
|
|
121
|
+
onClick: () => u(!0),
|
|
112
122
|
selectedItem: b
|
|
113
123
|
}
|
|
114
124
|
),
|
|
115
125
|
/* @__PURE__ */ e.jsx(
|
|
116
|
-
|
|
126
|
+
L,
|
|
117
127
|
{
|
|
118
128
|
isOpen: _,
|
|
119
|
-
onClose: () =>
|
|
129
|
+
onClose: () => u(!1),
|
|
120
130
|
actions: P,
|
|
121
|
-
selectedKeys: [
|
|
131
|
+
selectedKeys: [p],
|
|
122
132
|
disabledKeys: l
|
|
123
133
|
}
|
|
124
134
|
)
|
|
@@ -135,17 +145,17 @@ function F({
|
|
|
135
145
|
/* @__PURE__ */ e.jsx(
|
|
136
146
|
"input",
|
|
137
147
|
{
|
|
138
|
-
ref:
|
|
148
|
+
ref: d,
|
|
139
149
|
type: "hidden",
|
|
140
150
|
name: r,
|
|
141
|
-
value:
|
|
151
|
+
value: p,
|
|
142
152
|
"data-testid": "hidden-select-container"
|
|
143
153
|
}
|
|
144
154
|
),
|
|
145
155
|
/* @__PURE__ */ e.jsxs(
|
|
146
156
|
n.Root,
|
|
147
157
|
{
|
|
148
|
-
value:
|
|
158
|
+
value: p,
|
|
149
159
|
onValueChange: k,
|
|
150
160
|
onOpenChange: B,
|
|
151
161
|
disabled: a,
|
|
@@ -157,6 +167,7 @@ function F({
|
|
|
157
167
|
isOpen: _,
|
|
158
168
|
ref: y,
|
|
159
169
|
disabled: a,
|
|
170
|
+
ariaLabel: o || r,
|
|
160
171
|
"data-testid": v,
|
|
161
172
|
selectedItem: b
|
|
162
173
|
}
|
|
@@ -191,8 +202,8 @@ function F({
|
|
|
191
202
|
}
|
|
192
203
|
);
|
|
193
204
|
}
|
|
194
|
-
|
|
205
|
+
q.displayName = "ProtonUISelect";
|
|
195
206
|
export {
|
|
196
|
-
|
|
207
|
+
q as Select
|
|
197
208
|
};
|
|
198
209
|
//# sourceMappingURL=Select.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.es.js","sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n forwardRef,\n ReactNode,\n useEffect,\n useRef,\n useState,\n type ForwardedRef,\n type CSSProperties,\n} from \"react\";\nimport { Select as RadixSelect } from \"radix-ui\";\nimport { useTheme } from \"../ThemeProvider\";\nimport { useBreakpoint } from \"../../hooks/useBreakpoint\";\nimport { BREAKPOINTS } from \"../../constants\";\nimport { csx } from \"../../utils\";\n\nimport { ActionMenu, type ActionMenuAction } from \"../ActionMenu/ActionMenu\";\nimport { CaretDown as CaretDownIcon } from \"../Icon\";\n\nimport \"./Select.css\";\nimport \"../Menu/Menu.css\";\nimport \"../Elevation/Elevation.css\";\n\ninterface SelectButtonProps {\n disabled?: boolean;\n isOpen?: boolean;\n selectedItem?: SelectItem;\n onClick?: () => void;\n isRounded?: boolean;\n \"data-testid\"?: string;\n}\n\nconst SelectButton = forwardRef<HTMLButtonElement, SelectButtonProps>(\n (\n { disabled, isOpen, onClick, isRounded, selectedItem, \"data-testid\": testId },\n ref: ForwardedRef<HTMLButtonElement>,\n ) => {\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"combobox\"\n aria-expanded={isOpen}\n aria-autocomplete=\"none\"\n data-state={isOpen ? \"open\" : \"closed\"}\n data-testid={testId}\n disabled={disabled}\n onClick={onClick}\n className={csx(\n \"proton-Select__trigger\",\n \"proton-Elevation--glass\",\n disabled && \"proton-Select__trigger--disabled\",\n !isOpen && \"proton-Select__trigger--closed\",\n isOpen && \"proton-Select__trigger--opened\",\n isRounded && \"proton-Select__trigger--rounded\",\n )}\n >\n <span className=\"proton-Select__value\">\n {selectedItem ? selectedItem.label : \"Select an option\"}\n </span>\n <span\n className={csx(\n \"proton-Select__trigger_icon\",\n isOpen && \"proton-Select__trigger_icon--flipped\",\n )}\n >\n <CaretDownIcon size={16} />\n </span>\n </button>\n );\n },\n);\n\nSelectButton.displayName = \"ProtonUISelectButton\";\n\nexport interface SelectItem {\n /** The label to display for the item */\n label: string;\n\n /** The key of the item */\n key: string;\n\n /** The URL to navigate to when the item is clicked, turns item into an a tag */\n to?: string;\n}\n\nexport interface SelectProps {\n /** Array of keys that should be disabled\n * @example [\"Thing 1\", \"Thing 2\"]\n */\n disabledKeys?: string[];\n\n /** The key of the default selected item */\n defaultSelectedKey?: string;\n\n /** Test ID for the select */\n \"data-testid\"?: string;\n\n /** Whether the select is disabled */\n isDisabled?: boolean;\n\n /** Array of items to display\n * @example [{ key: \"thing-1\", label: \"Thing 1\" }, { key: \"thing-2\", label: \"Thing 2\" }]\n * @see {@link SelectItem}\n */\n items: SelectItem[];\n\n /** Whether the select button is rounded\n * @default false\n */\n isRounded?: boolean;\n\n /** Label to display above the select\n * @external https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#text\n */\n label?: string;\n\n /** The name of the select field */\n name: string;\n\n /** Callback fired when the menu closes */\n onClose?: () => void;\n\n /** Callback fired when the menu opens */\n onOpen?: () => void;\n\n /** Callback fired when selection changes */\n onSelectionChange?: (key: string) => void;\n\n /** Currently selected key */\n selectedKey?: string;\n}\n\n/**\n * A dropdown select menu that opens a popover on desktop and an action menu on mobile/touch devices.\n * Supports controlled and uncontrolled modes.\n *\n * API:\n * - {@link SelectProps}\n */\nexport function Select({\n label,\n name,\n isDisabled,\n disabledKeys,\n selectedKey,\n onSelectionChange,\n defaultSelectedKey,\n onOpen,\n onClose,\n items,\n isRounded = false,\n \"data-testid\": testId,\n}: SelectProps) {\n const [isOpen, setIsOpen] = useState(false);\n const isControlled = selectedKey !== undefined;\n const [internalSelectedKey, setInternalSelectedKey] = useState(\n defaultSelectedKey ?? \"\",\n );\n const { className: themeClass, style: themeStyle } = useTheme();\n const isMobile = useBreakpoint(BREAKPOINTS.MEDIUM);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const hiddenInputRef = useRef<HTMLInputElement>(null);\n\n // Handle controlled vs uncontrolled state\n const currentSelectedKey = isControlled\n ? (selectedKey as string)\n : internalSelectedKey;\n const selectedItem = items.find((item) => item.key === currentSelectedKey);\n\n const handleValueChange = (value: string) => {\n if (!isControlled) {\n setInternalSelectedKey(value);\n }\n onSelectionChange?.(value);\n\n // Update hidden input for form submission\n if (hiddenInputRef.current) {\n hiddenInputRef.current.value = value;\n hiddenInputRef.current.dispatchEvent(\n new Event(\"change\", { bubbles: true }),\n );\n }\n };\n\n const handleOpenChange = (open: boolean) => {\n setIsOpen(open);\n if (open) {\n onOpen?.();\n } else {\n onClose?.();\n }\n };\n\n // Update internal state when controlled selectedKey changes\n useEffect(() => {\n if (isControlled) {\n setInternalSelectedKey(selectedKey);\n }\n }, [isControlled]);\n\n const actionItems: ActionMenuAction[] = items.map((item) => ({\n key: item.key,\n label: item.label,\n to: item.to,\n onAction: () => {\n handleValueChange(item.key);\n setIsOpen(false);\n },\n }));\n\n if (isMobile) {\n return (\n <div\n className=\"proton-Select\"\n aria-label={label || name}\n aria-disabled={isDisabled}\n >\n {label && (\n <div className=\"proton-Select__label\" data-testid=\"select-label\">\n {label}\n </div>\n )}\n\n {/* Hidden input for form submission */}\n <input\n ref={hiddenInputRef}\n type=\"hidden\"\n name={name}\n value={currentSelectedKey}\n data-testid=\"hidden-select-container\"\n />\n\n <SelectButton\n isOpen={isOpen}\n isRounded={isRounded}\n ref={triggerRef}\n disabled={isDisabled}\n data-testid={testId}\n onClick={() => setIsOpen(true)}\n selectedItem={selectedItem}\n />\n\n <ActionMenu\n isOpen={isOpen}\n onClose={() => setIsOpen(false)}\n actions={actionItems}\n selectedKeys={[currentSelectedKey]}\n disabledKeys={disabledKeys}\n />\n </div>\n );\n }\n\n return (\n <div\n className=\"proton-Select\"\n aria-label={label || name}\n aria-disabled={isDisabled}\n >\n {label && (\n <div className=\"proton-Select__label\" data-testid=\"select-label\">\n {label}\n </div>\n )}\n\n {/* Hidden input for form submission */}\n <input\n ref={hiddenInputRef}\n type=\"hidden\"\n name={name}\n value={currentSelectedKey}\n data-testid=\"hidden-select-container\"\n />\n\n <RadixSelect.Root\n value={currentSelectedKey}\n onValueChange={handleValueChange}\n onOpenChange={handleOpenChange}\n disabled={isDisabled}\n >\n <RadixSelect.Trigger asChild>\n <SelectButton\n isRounded={isRounded}\n isOpen={isOpen}\n ref={triggerRef}\n disabled={isDisabled}\n data-testid={testId}\n selectedItem={selectedItem}\n />\n </RadixSelect.Trigger>\n\n <RadixSelect.Portal>\n <RadixSelect.Content\n className={csx(\n \"proton-Menu\",\n \"proton-MenuTrigger__menu\",\n \"proton-Elevation--glass\",\n themeClass,\n )}\n style={themeStyle as CSSProperties}\n position=\"popper\"\n >\n <RadixSelect.Viewport>\n {items.map((item) => (\n <RadixSelect.Item\n key={item.key}\n value={item.key}\n disabled={disabledKeys?.includes(item.key)}\n className=\"proton-Menu__item\"\n >\n <RadixSelect.ItemText>{item.label}</RadixSelect.ItemText>\n </RadixSelect.Item>\n ))}\n </RadixSelect.Viewport>\n </RadixSelect.Content>\n </RadixSelect.Portal>\n </RadixSelect.Root>\n </div>\n );\n}\n\nSelect.displayName = \"ProtonUISelect\";\n"],"names":["SelectButton","forwardRef","disabled","isOpen","onClick","isRounded","selectedItem","testId","ref","jsxs","csx","jsx","CaretDownIcon","Select","label","name","isDisabled","disabledKeys","selectedKey","onSelectionChange","defaultSelectedKey","onOpen","onClose","items","setIsOpen","useState","isControlled","internalSelectedKey","setInternalSelectedKey","themeClass","themeStyle","useTheme","isMobile","useBreakpoint","BREAKPOINTS","triggerRef","useRef","hiddenInputRef","currentSelectedKey","item","handleValueChange","value","handleOpenChange","open","useEffect","actionItems","ActionMenu","RadixSelect"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Select.es.js","sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n forwardRef,\n ReactNode,\n useEffect,\n useRef,\n useState,\n type ForwardedRef,\n type CSSProperties,\n} from \"react\";\nimport { Select as RadixSelect } from \"radix-ui\";\nimport { useTheme } from \"../ThemeProvider\";\nimport { useBreakpoint } from \"../../hooks/useBreakpoint\";\nimport { BREAKPOINTS } from \"../../constants\";\nimport { csx } from \"../../utils\";\n\nimport { ActionMenu, type ActionMenuAction } from \"../ActionMenu/ActionMenu\";\nimport { CaretDown as CaretDownIcon } from \"../Icon\";\n\nimport \"./Select.css\";\nimport \"../Menu/Menu.css\";\nimport \"../Elevation/Elevation.css\";\n\ninterface SelectButtonProps {\n disabled?: boolean;\n isOpen?: boolean;\n selectedItem?: SelectItem;\n onClick?: () => void;\n isRounded?: boolean;\n ariaLabel?: string;\n \"data-testid\"?: string;\n}\n\nconst SelectButton = forwardRef<HTMLButtonElement, SelectButtonProps>(\n (\n {\n disabled,\n isOpen,\n onClick,\n isRounded,\n selectedItem,\n ariaLabel,\n \"data-testid\": testId,\n },\n ref: ForwardedRef<HTMLButtonElement>,\n ) => {\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"combobox\"\n aria-label={ariaLabel}\n aria-expanded={isOpen}\n aria-autocomplete=\"none\"\n data-state={isOpen ? \"open\" : \"closed\"}\n data-testid={testId}\n disabled={disabled}\n onClick={onClick}\n className={csx(\n \"proton-Select__trigger\",\n \"proton-Elevation--glass\",\n disabled && \"proton-Select__trigger--disabled\",\n !isOpen && \"proton-Select__trigger--closed\",\n isOpen && \"proton-Select__trigger--opened\",\n isRounded && \"proton-Select__trigger--rounded\",\n )}\n >\n <span className=\"proton-Select__value\">\n {selectedItem ? selectedItem.label : \"Select an option\"}\n </span>\n <span\n className={csx(\n \"proton-Select__trigger_icon\",\n isOpen && \"proton-Select__trigger_icon--flipped\",\n )}\n >\n <CaretDownIcon size={16} />\n </span>\n </button>\n );\n },\n);\n\nSelectButton.displayName = \"ProtonUISelectButton\";\n\nexport interface SelectItem {\n /** The label to display for the item */\n label: string;\n\n /** The key of the item */\n key: string;\n\n /** The URL to navigate to when the item is clicked, turns item into an a tag */\n to?: string;\n}\n\nexport interface SelectProps {\n /** Array of keys that should be disabled\n * @example [\"Thing 1\", \"Thing 2\"]\n */\n disabledKeys?: string[];\n\n /** The key of the default selected item */\n defaultSelectedKey?: string;\n\n /** Test ID for the select */\n \"data-testid\"?: string;\n\n /** Whether the select is disabled */\n isDisabled?: boolean;\n\n /** Array of items to display\n * @example [{ key: \"thing-1\", label: \"Thing 1\" }, { key: \"thing-2\", label: \"Thing 2\" }]\n * @see {@link SelectItem}\n */\n items: SelectItem[];\n\n /** Whether the select button is rounded\n * @default false\n */\n isRounded?: boolean;\n\n /** Label to display above the select\n * @external https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#text\n */\n label?: string;\n\n /** The name of the select field */\n name: string;\n\n /** Callback fired when the menu closes */\n onClose?: () => void;\n\n /** Callback fired when the menu opens */\n onOpen?: () => void;\n\n /** Callback fired when selection changes */\n onSelectionChange?: (key: string) => void;\n\n /** Currently selected key */\n selectedKey?: string;\n}\n\n/**\n * A dropdown select menu that opens a popover on desktop and an action menu on mobile/touch devices.\n * Supports controlled and uncontrolled modes.\n *\n * API:\n * - {@link SelectProps}\n */\nexport function Select({\n label,\n name,\n isDisabled,\n disabledKeys,\n selectedKey,\n onSelectionChange,\n defaultSelectedKey,\n onOpen,\n onClose,\n items,\n isRounded = false,\n \"data-testid\": testId,\n}: SelectProps) {\n const [isOpen, setIsOpen] = useState(false);\n const isControlled = selectedKey !== undefined;\n const [internalSelectedKey, setInternalSelectedKey] = useState(\n defaultSelectedKey ?? \"\",\n );\n const { className: themeClass, style: themeStyle } = useTheme();\n const isMobile = useBreakpoint(BREAKPOINTS.MEDIUM);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const hiddenInputRef = useRef<HTMLInputElement>(null);\n\n // Handle controlled vs uncontrolled state\n const currentSelectedKey = isControlled\n ? (selectedKey as string)\n : internalSelectedKey;\n const selectedItem = items.find((item) => item.key === currentSelectedKey);\n\n const handleValueChange = (value: string) => {\n if (!isControlled) {\n setInternalSelectedKey(value);\n }\n onSelectionChange?.(value);\n\n // Update hidden input for form submission\n if (hiddenInputRef.current) {\n hiddenInputRef.current.value = value;\n hiddenInputRef.current.dispatchEvent(\n new Event(\"change\", { bubbles: true }),\n );\n }\n };\n\n const handleOpenChange = (open: boolean) => {\n setIsOpen(open);\n if (open) {\n onOpen?.();\n } else {\n onClose?.();\n }\n };\n\n // Update internal state when controlled selectedKey changes\n useEffect(() => {\n if (isControlled) {\n setInternalSelectedKey(selectedKey);\n }\n }, [isControlled]);\n\n const actionItems: ActionMenuAction[] = items.map((item) => ({\n key: item.key,\n label: item.label,\n to: item.to,\n onAction: () => {\n handleValueChange(item.key);\n setIsOpen(false);\n },\n }));\n\n if (isMobile) {\n return (\n <div\n className=\"proton-Select\"\n aria-label={label || name}\n aria-disabled={isDisabled}\n >\n {label && (\n <div className=\"proton-Select__label\" data-testid=\"select-label\">\n {label}\n </div>\n )}\n\n {/* Hidden input for form submission */}\n <input\n ref={hiddenInputRef}\n type=\"hidden\"\n name={name}\n value={currentSelectedKey}\n data-testid=\"hidden-select-container\"\n />\n\n <SelectButton\n isOpen={isOpen}\n isRounded={isRounded}\n ref={triggerRef}\n disabled={isDisabled}\n ariaLabel={label || name}\n data-testid={testId}\n onClick={() => setIsOpen(true)}\n selectedItem={selectedItem}\n />\n\n <ActionMenu\n isOpen={isOpen}\n onClose={() => setIsOpen(false)}\n actions={actionItems}\n selectedKeys={[currentSelectedKey]}\n disabledKeys={disabledKeys}\n />\n </div>\n );\n }\n\n return (\n <div\n className=\"proton-Select\"\n aria-label={label || name}\n aria-disabled={isDisabled}\n >\n {label && (\n <div className=\"proton-Select__label\" data-testid=\"select-label\">\n {label}\n </div>\n )}\n\n {/* Hidden input for form submission */}\n <input\n ref={hiddenInputRef}\n type=\"hidden\"\n name={name}\n value={currentSelectedKey}\n data-testid=\"hidden-select-container\"\n />\n\n <RadixSelect.Root\n value={currentSelectedKey}\n onValueChange={handleValueChange}\n onOpenChange={handleOpenChange}\n disabled={isDisabled}\n >\n <RadixSelect.Trigger asChild>\n <SelectButton\n isRounded={isRounded}\n isOpen={isOpen}\n ref={triggerRef}\n disabled={isDisabled}\n ariaLabel={label || name}\n data-testid={testId}\n selectedItem={selectedItem}\n />\n </RadixSelect.Trigger>\n\n <RadixSelect.Portal>\n <RadixSelect.Content\n className={csx(\n \"proton-Menu\",\n \"proton-MenuTrigger__menu\",\n \"proton-Elevation--glass\",\n themeClass,\n )}\n style={themeStyle as CSSProperties}\n position=\"popper\"\n >\n <RadixSelect.Viewport>\n {items.map((item) => (\n <RadixSelect.Item\n key={item.key}\n value={item.key}\n disabled={disabledKeys?.includes(item.key)}\n className=\"proton-Menu__item\"\n >\n <RadixSelect.ItemText>{item.label}</RadixSelect.ItemText>\n </RadixSelect.Item>\n ))}\n </RadixSelect.Viewport>\n </RadixSelect.Content>\n </RadixSelect.Portal>\n </RadixSelect.Root>\n </div>\n );\n}\n\nSelect.displayName = \"ProtonUISelect\";\n"],"names":["SelectButton","forwardRef","disabled","isOpen","onClick","isRounded","selectedItem","ariaLabel","testId","ref","jsxs","csx","jsx","CaretDownIcon","Select","label","name","isDisabled","disabledKeys","selectedKey","onSelectionChange","defaultSelectedKey","onOpen","onClose","items","setIsOpen","useState","isControlled","internalSelectedKey","setInternalSelectedKey","themeClass","themeStyle","useTheme","isMobile","useBreakpoint","BREAKPOINTS","triggerRef","useRef","hiddenInputRef","currentSelectedKey","item","handleValueChange","value","handleOpenChange","open","useEffect","actionItems","ActionMenu","RadixSelect"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("../../node_modules/react/jsx-runtime.cjs.js"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("../../node_modules/react/jsx-runtime.cjs.js"),x=require("react"),S=require("radix-ui");;/* empty css */const w=require("../../utils/string.cjs.js");function v({defaultOn:p,isOn:n,isDisabled:s,onChange:i,label:e,children:o,"data-testid":u}){const c=n!==void 0,[l,j]=x.useState(p||!1),r=c?!!n:l,d=x.useId(),m={type:"checkbox",role:"switch",checked:r,disabled:s,"aria-label":e||void 0,"aria-describedby":o?d:void 0,onChange:h=>{if(s)return;const a=h.target.checked;c||j(a),i==null||i(a)}};return t.jsxRuntimeExports.jsx("div",{className:w.csx("proton-Switch",s&&"proton-Switch--disabled",r&&"proton-Switch--on"),"data-on":r||void 0,"data-disabled":s||void 0,"data-testid":u||void 0,children:t.jsxRuntimeExports.jsxs("label",{className:"proton-Switch__control",children:[t.jsxRuntimeExports.jsx(S.VisuallyHidden.Root,{children:t.jsxRuntimeExports.jsx("input",{...m})}),e&&t.jsxRuntimeExports.jsx("span",{className:"proton-Switch__label",children:e}),t.jsxRuntimeExports.jsxs("div",{className:"proton-Switch__wrapper",children:[t.jsxRuntimeExports.jsx("div",{className:"proton-Switch__toggle",children:t.jsxRuntimeExports.jsx("div",{className:"proton-Switch__slider"})}),o&&t.jsxRuntimeExports.jsx("div",{id:d,className:"proton-Switch__description",children:o})]})]})})}exports.Switch=v;
|
|
2
2
|
//# sourceMappingURL=Switch.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Switch.cjs.js","sources":["../../../src/components/Switch/Switch.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, type ChangeEvent } from \"react\";\nimport { VisuallyHidden } from \"radix-ui\";\n\nimport { csx } from \"../../utils\";\n\nimport \"./Switch.css\";\n\nexport interface SwitchProps {\n /**\n * Whether the Switch is in the 'on' state (uncontrolled).\n */\n defaultOn?: boolean;\n /**\n * Whether the Switch is in the 'on' state. Providing this prop causes the\n * component to become controlled.\n */\n isOn?: boolean;\n /**\n * Should the input be non-interactive?\n */\n isDisabled?: boolean;\n /**\n * Called when the Switch's on state changes.\n */\n onChange?: (isOn: boolean) => void;\n /**\n * The string used for the input label. Forwarded to `aria-label`.\n */\n label?: string;\n /**\n * The text or component to be rendered as the Switch's description.\n */\n children?: React.ReactNode;\n /** The test ID for the switch. */\n \"data-testid\"?: string;\n}\n\n/**\n * A toggle switch component for boolean state control with support for controlled and uncontrolled modes.\n *\n * API:\n * - {@link SwitchProps}\n */\nexport function Switch({\n defaultOn,\n isOn: controlledIsOn,\n isDisabled,\n onChange,\n label,\n children,\n \"data-testid\": testId,\n}: SwitchProps) {\n const isControlled = controlledIsOn !== undefined;\n const [internalOn, setInternalOn] = useState(defaultOn || false);\n const isOn = isControlled ? Boolean(controlledIsOn) : internalOn;\n\n const inputProps = {\n type: \"checkbox\" as const,\n role: \"switch\" as const,\n checked: isOn,\n disabled: isDisabled,\n onChange: (e: ChangeEvent<HTMLInputElement>) => {\n if (isDisabled) return;\n const next = e.target.checked;\n if (!isControlled) setInternalOn(next);\n onChange?.(next);\n },\n };\n\n return (\n <
|
|
1
|
+
{"version":3,"file":"Switch.cjs.js","sources":["../../../src/components/Switch/Switch.tsx"],"sourcesContent":["\"use client\";\n\nimport { useId, useState, type ChangeEvent } from \"react\";\nimport { VisuallyHidden } from \"radix-ui\";\n\nimport { csx } from \"../../utils\";\n\nimport \"./Switch.css\";\n\nexport interface SwitchProps {\n /**\n * Whether the Switch is in the 'on' state (uncontrolled).\n */\n defaultOn?: boolean;\n /**\n * Whether the Switch is in the 'on' state. Providing this prop causes the\n * component to become controlled.\n */\n isOn?: boolean;\n /**\n * Should the input be non-interactive?\n */\n isDisabled?: boolean;\n /**\n * Called when the Switch's on state changes.\n */\n onChange?: (isOn: boolean) => void;\n /**\n * The string used for the input label. Forwarded to `aria-label`.\n */\n label?: string;\n /**\n * The text or component to be rendered as the Switch's description.\n */\n children?: React.ReactNode;\n /** The test ID for the switch. */\n \"data-testid\"?: string;\n}\n\n/**\n * A toggle switch component for boolean state control with support for controlled and uncontrolled modes.\n *\n * API:\n * - {@link SwitchProps}\n */\nexport function Switch({\n defaultOn,\n isOn: controlledIsOn,\n isDisabled,\n onChange,\n label,\n children,\n \"data-testid\": testId,\n}: SwitchProps) {\n const isControlled = controlledIsOn !== undefined;\n const [internalOn, setInternalOn] = useState(defaultOn || false);\n const isOn = isControlled ? Boolean(controlledIsOn) : internalOn;\n const descriptionId = useId();\n\n const inputProps = {\n type: \"checkbox\" as const,\n role: \"switch\" as const,\n checked: isOn,\n disabled: isDisabled,\n \"aria-label\": label || undefined,\n \"aria-describedby\": children ? descriptionId : undefined,\n onChange: (e: ChangeEvent<HTMLInputElement>) => {\n if (isDisabled) return;\n const next = e.target.checked;\n if (!isControlled) setInternalOn(next);\n onChange?.(next);\n },\n };\n\n return (\n <div\n className={csx(\n \"proton-Switch\",\n isDisabled && \"proton-Switch--disabled\",\n isOn && \"proton-Switch--on\",\n )}\n data-on={isOn || undefined}\n data-disabled={isDisabled || undefined}\n data-testid={testId || undefined}\n >\n <label className=\"proton-Switch__control\">\n <VisuallyHidden.Root>\n <input {...inputProps} />\n </VisuallyHidden.Root>\n {label && <span className=\"proton-Switch__label\">{label}</span>}\n <div className=\"proton-Switch__wrapper\">\n <div className=\"proton-Switch__toggle\">\n <div className=\"proton-Switch__slider\" />\n </div>\n {children && (\n <div id={descriptionId} className=\"proton-Switch__description\">\n {children}\n </div>\n )}\n </div>\n </label>\n </div>\n );\n}\n"],"names":["Switch","defaultOn","controlledIsOn","isDisabled","onChange","label","children","testId","isControlled","internalOn","setInternalOn","useState","isOn","descriptionId","useId","inputProps","e","next","jsx","csx","jsxs","VisuallyHidden"],"mappings":"oQA6CO,SAASA,EAAO,CACrB,UAAAC,EACA,KAAMC,EACN,WAAAC,EACA,SAAAC,EACA,MAAAC,EACA,SAAAC,EACA,cAAeC,CACjB,EAAgB,CACd,MAAMC,EAAeN,IAAmB,OAClC,CAACO,EAAYC,CAAa,EAAIC,EAAAA,SAASV,GAAa,EAAK,EACzDW,EAAOJ,EAAe,EAAQN,EAAkBO,EAChDI,EAAgBC,EAAAA,MAAA,EAEhBC,EAAa,CACjB,KAAM,WACN,KAAM,SACN,QAASH,EACT,SAAUT,EACV,aAAcE,GAAS,OACvB,mBAAoBC,EAAWO,EAAgB,OAC/C,SAAWG,GAAqC,CAC9C,GAAIb,EAAY,OAChB,MAAMc,EAAOD,EAAE,OAAO,QACjBR,GAAcE,EAAcO,CAAI,EACrCb,GAAA,MAAAA,EAAWa,EACb,CAAA,EAGF,OACEC,EAAAA,kBAAAA,IAAC,MAAA,CACC,UAAWC,EAAAA,IACT,gBACAhB,GAAc,0BACdS,GAAQ,mBAAA,EAEV,UAASA,GAAQ,OACjB,gBAAeT,GAAc,OAC7B,cAAaI,GAAU,OAEvB,SAAAa,EAAAA,kBAAAA,KAAC,QAAA,CAAM,UAAU,yBACf,SAAA,CAAAF,wBAACG,EAAAA,eAAe,KAAf,CACC,iCAAC,QAAA,CAAO,GAAGN,EAAY,EACzB,EACCV,GAASa,EAAAA,kBAAAA,IAAC,OAAA,CAAK,UAAU,uBAAwB,SAAAb,EAAM,EACxDe,EAAAA,kBAAAA,KAAC,MAAA,CAAI,UAAU,yBACb,SAAA,CAAAF,EAAAA,kBAAAA,IAAC,OAAI,UAAU,wBACb,iCAAC,MAAA,CAAI,UAAU,wBAAwB,CAAA,CACzC,EACCZ,GACCY,EAAAA,kBAAAA,IAAC,MAAA,CAAI,GAAIL,EAAe,UAAU,6BAC/B,SAAAP,CAAA,CACH,CAAA,CAAA,CAEJ,CAAA,CAAA,CACF,CAAA,CAAA,CAGN"}
|
|
@@ -1,52 +1,53 @@
|
|
|
1
1
|
import { j as t } from "../../node_modules/react/jsx-runtime.es.js";
|
|
2
|
-
import { useState as
|
|
3
|
-
import { VisuallyHidden as
|
|
2
|
+
import { useState as _, useId as j } from "react";
|
|
3
|
+
import { VisuallyHidden as v } from "radix-ui";
|
|
4
4
|
/* empty css */
|
|
5
|
-
import { csx as
|
|
6
|
-
function
|
|
7
|
-
defaultOn:
|
|
8
|
-
isOn:
|
|
5
|
+
import { csx as S } from "../../utils/string.es.js";
|
|
6
|
+
function y({
|
|
7
|
+
defaultOn: p,
|
|
8
|
+
isOn: c,
|
|
9
9
|
isDisabled: o,
|
|
10
10
|
onChange: i,
|
|
11
11
|
label: s,
|
|
12
|
-
children:
|
|
13
|
-
"data-testid":
|
|
12
|
+
children: r,
|
|
13
|
+
"data-testid": l
|
|
14
14
|
}) {
|
|
15
|
-
const
|
|
15
|
+
const d = c !== void 0, [m, h] = _(p || !1), e = d ? !!c : m, n = j(), x = {
|
|
16
16
|
type: "checkbox",
|
|
17
17
|
role: "switch",
|
|
18
|
-
checked:
|
|
18
|
+
checked: e,
|
|
19
19
|
disabled: o,
|
|
20
|
-
|
|
20
|
+
"aria-label": s || void 0,
|
|
21
|
+
"aria-describedby": r ? n : void 0,
|
|
22
|
+
onChange: (w) => {
|
|
21
23
|
if (o) return;
|
|
22
|
-
const a =
|
|
23
|
-
|
|
24
|
+
const a = w.target.checked;
|
|
25
|
+
d || h(a), i == null || i(a);
|
|
24
26
|
}
|
|
25
27
|
};
|
|
26
|
-
return /* @__PURE__ */ t.
|
|
27
|
-
"
|
|
28
|
+
return /* @__PURE__ */ t.jsx(
|
|
29
|
+
"div",
|
|
28
30
|
{
|
|
29
|
-
className:
|
|
31
|
+
className: S(
|
|
30
32
|
"proton-Switch",
|
|
31
33
|
o && "proton-Switch--disabled",
|
|
32
|
-
|
|
34
|
+
e && "proton-Switch--on"
|
|
33
35
|
),
|
|
34
|
-
"data-on":
|
|
36
|
+
"data-on": e || void 0,
|
|
35
37
|
"data-disabled": o || void 0,
|
|
36
|
-
"data-testid":
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
/* @__PURE__ */ t.jsx(
|
|
40
|
-
s && /* @__PURE__ */ t.jsx("div", { className: "proton-Switch__label", children: s }),
|
|
38
|
+
"data-testid": l || void 0,
|
|
39
|
+
children: /* @__PURE__ */ t.jsxs("label", { className: "proton-Switch__control", children: [
|
|
40
|
+
/* @__PURE__ */ t.jsx(v.Root, { children: /* @__PURE__ */ t.jsx("input", { ...x }) }),
|
|
41
|
+
s && /* @__PURE__ */ t.jsx("span", { className: "proton-Switch__label", children: s }),
|
|
41
42
|
/* @__PURE__ */ t.jsxs("div", { className: "proton-Switch__wrapper", children: [
|
|
42
43
|
/* @__PURE__ */ t.jsx("div", { className: "proton-Switch__toggle", children: /* @__PURE__ */ t.jsx("div", { className: "proton-Switch__slider" }) }),
|
|
43
|
-
|
|
44
|
+
r && /* @__PURE__ */ t.jsx("div", { id: n, className: "proton-Switch__description", children: r })
|
|
44
45
|
] })
|
|
45
|
-
]
|
|
46
|
+
] })
|
|
46
47
|
}
|
|
47
48
|
);
|
|
48
49
|
}
|
|
49
50
|
export {
|
|
50
|
-
|
|
51
|
+
y as Switch
|
|
51
52
|
};
|
|
52
53
|
//# sourceMappingURL=Switch.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Switch.es.js","sources":["../../../src/components/Switch/Switch.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, type ChangeEvent } from \"react\";\nimport { VisuallyHidden } from \"radix-ui\";\n\nimport { csx } from \"../../utils\";\n\nimport \"./Switch.css\";\n\nexport interface SwitchProps {\n /**\n * Whether the Switch is in the 'on' state (uncontrolled).\n */\n defaultOn?: boolean;\n /**\n * Whether the Switch is in the 'on' state. Providing this prop causes the\n * component to become controlled.\n */\n isOn?: boolean;\n /**\n * Should the input be non-interactive?\n */\n isDisabled?: boolean;\n /**\n * Called when the Switch's on state changes.\n */\n onChange?: (isOn: boolean) => void;\n /**\n * The string used for the input label. Forwarded to `aria-label`.\n */\n label?: string;\n /**\n * The text or component to be rendered as the Switch's description.\n */\n children?: React.ReactNode;\n /** The test ID for the switch. */\n \"data-testid\"?: string;\n}\n\n/**\n * A toggle switch component for boolean state control with support for controlled and uncontrolled modes.\n *\n * API:\n * - {@link SwitchProps}\n */\nexport function Switch({\n defaultOn,\n isOn: controlledIsOn,\n isDisabled,\n onChange,\n label,\n children,\n \"data-testid\": testId,\n}: SwitchProps) {\n const isControlled = controlledIsOn !== undefined;\n const [internalOn, setInternalOn] = useState(defaultOn || false);\n const isOn = isControlled ? Boolean(controlledIsOn) : internalOn;\n\n const inputProps = {\n type: \"checkbox\" as const,\n role: \"switch\" as const,\n checked: isOn,\n disabled: isDisabled,\n onChange: (e: ChangeEvent<HTMLInputElement>) => {\n if (isDisabled) return;\n const next = e.target.checked;\n if (!isControlled) setInternalOn(next);\n onChange?.(next);\n },\n };\n\n return (\n <
|
|
1
|
+
{"version":3,"file":"Switch.es.js","sources":["../../../src/components/Switch/Switch.tsx"],"sourcesContent":["\"use client\";\n\nimport { useId, useState, type ChangeEvent } from \"react\";\nimport { VisuallyHidden } from \"radix-ui\";\n\nimport { csx } from \"../../utils\";\n\nimport \"./Switch.css\";\n\nexport interface SwitchProps {\n /**\n * Whether the Switch is in the 'on' state (uncontrolled).\n */\n defaultOn?: boolean;\n /**\n * Whether the Switch is in the 'on' state. Providing this prop causes the\n * component to become controlled.\n */\n isOn?: boolean;\n /**\n * Should the input be non-interactive?\n */\n isDisabled?: boolean;\n /**\n * Called when the Switch's on state changes.\n */\n onChange?: (isOn: boolean) => void;\n /**\n * The string used for the input label. Forwarded to `aria-label`.\n */\n label?: string;\n /**\n * The text or component to be rendered as the Switch's description.\n */\n children?: React.ReactNode;\n /** The test ID for the switch. */\n \"data-testid\"?: string;\n}\n\n/**\n * A toggle switch component for boolean state control with support for controlled and uncontrolled modes.\n *\n * API:\n * - {@link SwitchProps}\n */\nexport function Switch({\n defaultOn,\n isOn: controlledIsOn,\n isDisabled,\n onChange,\n label,\n children,\n \"data-testid\": testId,\n}: SwitchProps) {\n const isControlled = controlledIsOn !== undefined;\n const [internalOn, setInternalOn] = useState(defaultOn || false);\n const isOn = isControlled ? Boolean(controlledIsOn) : internalOn;\n const descriptionId = useId();\n\n const inputProps = {\n type: \"checkbox\" as const,\n role: \"switch\" as const,\n checked: isOn,\n disabled: isDisabled,\n \"aria-label\": label || undefined,\n \"aria-describedby\": children ? descriptionId : undefined,\n onChange: (e: ChangeEvent<HTMLInputElement>) => {\n if (isDisabled) return;\n const next = e.target.checked;\n if (!isControlled) setInternalOn(next);\n onChange?.(next);\n },\n };\n\n return (\n <div\n className={csx(\n \"proton-Switch\",\n isDisabled && \"proton-Switch--disabled\",\n isOn && \"proton-Switch--on\",\n )}\n data-on={isOn || undefined}\n data-disabled={isDisabled || undefined}\n data-testid={testId || undefined}\n >\n <label className=\"proton-Switch__control\">\n <VisuallyHidden.Root>\n <input {...inputProps} />\n </VisuallyHidden.Root>\n {label && <span className=\"proton-Switch__label\">{label}</span>}\n <div className=\"proton-Switch__wrapper\">\n <div className=\"proton-Switch__toggle\">\n <div className=\"proton-Switch__slider\" />\n </div>\n {children && (\n <div id={descriptionId} className=\"proton-Switch__description\">\n {children}\n </div>\n )}\n </div>\n </label>\n </div>\n );\n}\n"],"names":["Switch","defaultOn","controlledIsOn","isDisabled","onChange","label","children","testId","isControlled","internalOn","setInternalOn","useState","isOn","descriptionId","useId","inputProps","e","next","jsx","csx","jsxs","VisuallyHidden"],"mappings":";;;;;AA6CO,SAASA,EAAO;AAAA,EACrB,WAAAC;AAAA,EACA,MAAMC;AAAA,EACN,YAAAC;AAAA,EACA,UAAAC;AAAA,EACA,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,eAAeC;AACjB,GAAgB;AACd,QAAMC,IAAeN,MAAmB,QAClC,CAACO,GAAYC,CAAa,IAAIC,EAASV,KAAa,EAAK,GACzDW,IAAOJ,IAAe,EAAQN,IAAkBO,GAChDI,IAAgBC,EAAA,GAEhBC,IAAa;AAAA,IACjB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAASH;AAAA,IACT,UAAUT;AAAA,IACV,cAAcE,KAAS;AAAA,IACvB,oBAAoBC,IAAWO,IAAgB;AAAA,IAC/C,UAAU,CAACG,MAAqC;AAC9C,UAAIb,EAAY;AAChB,YAAMc,IAAOD,EAAE,OAAO;AACtB,MAAKR,KAAcE,EAAcO,CAAI,GACrCb,KAAA,QAAAA,EAAWa;AAAA,IACb;AAAA,EAAA;AAGF,SACEC,gBAAAA,EAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC;AAAA,QACT;AAAA,QACAhB,KAAc;AAAA,QACdS,KAAQ;AAAA,MAAA;AAAA,MAEV,WAASA,KAAQ;AAAA,MACjB,iBAAeT,KAAc;AAAA,MAC7B,eAAaI,KAAU;AAAA,MAEvB,UAAAa,gBAAAA,EAAAA,KAAC,SAAA,EAAM,WAAU,0BACf,UAAA;AAAA,QAAAF,gBAAAA,MAACG,EAAe,MAAf,EACC,gCAAC,SAAA,EAAO,GAAGN,GAAY,GACzB;AAAA,QACCV,KAASa,gBAAAA,EAAAA,IAAC,QAAA,EAAK,WAAU,wBAAwB,UAAAb,GAAM;AAAA,QACxDe,gBAAAA,EAAAA,KAAC,OAAA,EAAI,WAAU,0BACb,UAAA;AAAA,UAAAF,gBAAAA,EAAAA,IAAC,SAAI,WAAU,yBACb,gCAAC,OAAA,EAAI,WAAU,yBAAwB,EAAA,CACzC;AAAA,UACCZ,KACCY,gBAAAA,EAAAA,IAAC,OAAA,EAAI,IAAIL,GAAe,WAAU,8BAC/B,UAAAP,EAAA,CACH;AAAA,QAAA,EAAA,CAEJ;AAAA,MAAA,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AAGN;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../../../node_modules/react/jsx-runtime.cjs.js"),s=require("../BaseTable/Table.cjs.js"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../../../node_modules/react/jsx-runtime.cjs.js"),s=require("../BaseTable/Table.cjs.js"),D=require("../../Elevation/Elevation.cjs.js"),f=require("../../Tombstone/Tombstone.cjs.js"),_=require("../../Icon/IconComponents/ChevronUp.cjs.js"),q=require("./DataTableRow.cjs.js");;/* empty css */;/* empty css */const h=({columns:n,data:l=[],loading:j=!1,tombstoneComponent:p,error:x=!1,name:i,onRowClick:R,emptyMessage:E="Data Unavailable",errorMessage:T="An error occurred",loadingRows:C=5,"data-testid":d,memoize:g=!0,sortableColumns:y=[],sortedBy:u,sortDirection:c,onSort:b})=>{const o=n.filter(t=>!t.isHidden),S=t=>{if(!b)return;const a=u===t.id&&c==="ASC"?"DESC":"ASC";b(t.id,a)},v=t=>u!==t?"none":c==="ASC"?"ascending":"descending";return x?e.jsxRuntimeExports.jsx(m,{columns:o,message:typeof x=="string"?x:T,name:i,testId:d,isError:!0}):j?e.jsxRuntimeExports.jsx("div",{className:"proton-DataTable","data-testid":d,"aria-busy":"true","aria-label":`Loading ${i}...`,children:e.jsxRuntimeExports.jsxs(s.Table,{name:i,children:[e.jsxRuntimeExports.jsx(s.Table.Header,{children:o.map(t=>e.jsxRuntimeExports.jsx(s.Table.Column,{id:t.id,children:t.header},t.id))}),e.jsxRuntimeExports.jsx(s.Table.Body,{children:Array.from({length:C}).map((t,r)=>e.jsxRuntimeExports.jsx(s.Table.Row,{children:o.map(a=>e.jsxRuntimeExports.jsx(s.Table.Cell,{children:p||e.jsxRuntimeExports.jsx(f.Tombstone,{height:"1rem",width:r%3===0?"80%":r%3===1?"60%":"90%"})},a.id))},`loading-${r}`))})]})}):!l||l.length===0?e.jsxRuntimeExports.jsx(m,{columns:o,message:E,name:i,testId:d}):e.jsxRuntimeExports.jsx("div",{className:"proton-DataTable","data-testid":d,children:e.jsxRuntimeExports.jsxs(s.Table,{name:i,children:[e.jsxRuntimeExports.jsx(s.Table.Header,{children:o.map(t=>{const r=y.includes(t.id),a=v(t.id);return e.jsxRuntimeExports.jsx(s.Table.Column,{id:t.id,...r&&{"aria-sort":a},children:e.jsxRuntimeExports.jsxs("span",{className:"proton-DataTable__header-content",children:[t.header,r&&e.jsxRuntimeExports.jsx("button",{className:"proton-DataTable__sort-button",onClick:()=>S(t),"aria-label":`Sort by ${t.header}: ${a}`,type:"button",children:e.jsxRuntimeExports.jsx(_.ChevronUp,{size:12,color:a==="ascending"?"var(--proton-color__primary)":"currentColor"})})]})},t.id)})}),e.jsxRuntimeExports.jsx(s.Table.Body,{children:l.map((t,r)=>{const a=t;return e.jsxRuntimeExports.jsx(q.DataTableRow,{row:t,columns:o,rowIndex:r,onRowClick:R,memoize:g,dataTestId:a.dataTestId},a.key??r)})})]})})},m=({columns:n,message:l,name:j,testId:p,isError:x=!1})=>e.jsxRuntimeExports.jsx("div",{className:"proton-DataTable","data-testid":p,children:e.jsxRuntimeExports.jsxs(s.Table,{name:j,children:[e.jsxRuntimeExports.jsx(s.Table.Header,{children:n.map(i=>e.jsxRuntimeExports.jsx(s.Table.Column,{id:i.id,children:i.header},i.id))}),e.jsxRuntimeExports.jsx(s.Table.Body,{children:e.jsxRuntimeExports.jsx(s.Table.Row,{children:e.jsxRuntimeExports.jsx(s.Table.Cell,{colSpan:(n==null?void 0:n.length)||1,children:e.jsxRuntimeExports.jsx("div",{className:"proton-DataTable__message-cell",role:x?"alert":"status","aria-live":"polite",children:e.jsxRuntimeExports.jsx(D.Elevation,{children:e.jsxRuntimeExports.jsx("div",{className:"proton-DataTable__empty-cell",children:l})})})})})})]})});h.displayName="ProtonUIDataTable";exports.DataTable=h;
|
|
2
2
|
//# sourceMappingURL=DataTable.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTable.cjs.js","sources":["../../../../src/components/Table/DataTable/DataTable.tsx"],"sourcesContent":["\"use client\";\n\nimport { AriaAttributes, ReactNode } from \"react\";\nimport { deepEqual } from \"../../../utils/deepEqual\";\n\nimport { Table, TableRowData } from \"../BaseTable/Table\";\nimport { Elevation } from \"../../Elevation/Elevation\";\nimport { Tombstone } from \"../../Tombstone/Tombstone\";\nimport { ChevronUp } from \"../../Icon/IconComponents/ChevronUp\";\nimport { DataTableRow } from \"./DataTableRow\";\n\nimport \"../BaseTable/Table.css\";\nimport \"./DataTable.css\";\n\nexport type SortDirection = \"ASC\" | \"DESC\";\n\ntype SortingConfig =\n | {\n /** When sorting is enabled, all these props must be provided together. */\n sortableColumns: string[];\n sortedBy: string;\n sortDirection: SortDirection;\n onSort: (columnId: string, direction: SortDirection) => void;\n }\n | {\n /** When no sorting is needed, none of these props should be provided */\n sortableColumns?: never;\n sortedBy?: never;\n sortDirection?: never;\n onSort?: never;\n };\n\nexport interface DataTableColumn<T> {\n /** id for the column */\n id: string;\n /** Header text or component */\n header: ReactNode;\n /** Function to render cell content from row data */\n cell: (row: T) => ReactNode;\n /** Whether this column should be hidden */\n isHidden?: boolean;\n}\n\ninterface BaseDataTableProps<T = any> {\n /**\n * Array of column definitions\n * - {@link DataTableColumn}\n */\n columns: DataTableColumn<T>[];\n /**\n * Array of data objects to display. Can be empty array for loading/empty states\n * @default []\n * */\n data?: T[] | null;\n /**\n * Test ID for testing purposes\n * */\n \"data-testid\"?: string;\n /**\n * Error state\n * @default false\n */\n error?: boolean | string;\n /**\n * Custom empty state message\n * @default \"Data Unavailable\"\n */\n emptyMessage?: string;\n /**\n * Custom error message\n * @default \"An error occurred\"\n */\n errorMessage?: string;\n /** Callback when a row is clicked */\n onRowClick?: (row: T) => void;\n /** Loading state */\n loading?: boolean;\n /**\n * Number of skeleton rows to show in loading state\n * @default 5\n */\n loadingRows?: number;\n /**\n * Enable row-level memoization for performance optimization.\n * Uses deepEqual to compare row data. @see {@link deepEqual}\n * @default true\n */\n memoize?: boolean;\n /**\n * Table name/caption for accessibility. Provides essential context for screen readers.\n * */\n name: string;\n /** Optional tombstone component to use when loading */\n tombstoneComponent?: ReactNode;\n}\n\nexport type DataTableProps<T = any> = BaseDataTableProps<T> & SortingConfig;\n\n/**\n * DataTable is a declarative wrapper around the base Table component.\n * API:\n * - {@link DataTableProps}\n * - {@link SortingConfig}\n *\n * @note Row memoization is enabled by default. Rows only re-render when row data or index changes.\n */\nexport const DataTable = <T,>({\n columns,\n data = [],\n loading = false,\n tombstoneComponent,\n error = false,\n name,\n onRowClick,\n emptyMessage = \"Data Unavailable\",\n errorMessage = \"An error occurred\",\n loadingRows = 5,\n \"data-testid\": testId,\n memoize = true,\n sortableColumns = [],\n sortedBy,\n sortDirection,\n onSort,\n}: DataTableProps<T>) => {\n const visibleColumns = columns.filter((col) => !col.isHidden);\n\n const handleSortClick = (column: DataTableColumn<T>) => {\n if (!onSort) return;\n\n const isCurrentlySorted = sortedBy === column.id;\n const newDirection =\n isCurrentlySorted && sortDirection === \"ASC\" ? \"DESC\" : \"ASC\";\n\n onSort(column.id, newDirection);\n };\n\n const getSortState = (columnId: string): AriaAttributes[\"aria-sort\"] => {\n if (sortedBy !== columnId) return \"none\";\n return sortDirection === \"ASC\" ? \"ascending\" : \"descending\";\n };\n\n if (error) {\n return (\n <EmptyState\n columns={visibleColumns}\n message={typeof error === \"string\" ? error : errorMessage}\n name={name}\n testId={testId}\n isError\n />\n );\n }\n\n if (loading) {\n return (\n <div\n className=\"proton-DataTable\"\n data-testid={testId}\n aria-busy=\"true\"\n aria-label={`Loading ${name}...`}\n >\n <Table name={name}>\n <Table.Header>\n {visibleColumns.map((column) => (\n <Table.Column key={column.id} id={column.id}>\n {column.header}\n </Table.Column>\n ))}\n </Table.Header>\n <Table.Body>\n {Array.from({ length: loadingRows }).map((_, index) => (\n <Table.Row key={`loading-${index}`}>\n {visibleColumns.map((column) => (\n <Table.Cell key={column.id}>\n {tombstoneComponent || (\n <Tombstone\n height=\"1rem\"\n width={\n // cascading tombstone widths\n index % 3 === 0\n ? \"80%\"\n : index % 3 === 1\n ? \"60%\"\n : \"90%\"\n }\n />\n )}\n </Table.Cell>\n ))}\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </div>\n );\n }\n\n if (!data || data.length === 0) {\n return (\n <EmptyState\n columns={visibleColumns}\n message={emptyMessage}\n name={name}\n testId={testId}\n />\n );\n }\n\n return (\n <div className=\"proton-DataTable\" data-testid={testId}>\n <Table name={name}>\n <Table.Header>\n {visibleColumns.map((column) => {\n const isSortable = sortableColumns.includes(column.id);\n const sortState = getSortState(column.id);\n\n return (\n <Table.Column\n key={column.id}\n id={column.id}\n {...(isSortable && { \"aria-sort\": sortState })}\n >\n <span className=\"proton-DataTable__header-content\">\n {column.header}\n\n {isSortable && (\n <button\n className=\"proton-DataTable__sort-button\"\n onClick={() => handleSortClick(column)}\n aria-label={`Sort by ${column.header}: ${sortState}`}\n type=\"button\"\n >\n <ChevronUp\n size={12}\n color={\n sortState === \"ascending\"\n ? \"var(--proton-color__primary)\"\n : \"currentColor\"\n }\n />\n </button>\n )}\n </span>\n </Table.Column>\n );\n })}\n </Table.Header>\n <Table.Body>\n {data.map((row, index) => {\n const tableRow = row as TableRowData;\n\n return (\n <DataTableRow\n key={tableRow.key ?? index}\n row={row}\n columns={visibleColumns}\n rowIndex={index}\n onRowClick={onRowClick}\n memoize={memoize}\n dataTestId={tableRow.dataTestId}\n />\n );\n })}\n </Table.Body>\n </Table>\n </div>\n );\n};\n\nconst EmptyState = ({\n columns = [],\n message,\n name = \"Data\",\n testId,\n isError = false,\n}: Partial<DataTableProps> & {\n testId?: string;\n message: string;\n isError?: boolean;\n}) => {\n return (\n <div className=\"proton-DataTable\" data-testid={testId}>\n <Table name={name}>\n <Table.Header>\n {columns.map((column) => (\n <Table.Column key={column.id} id={column.id}>\n {column.header}\n </Table.Column>\n ))}\n </Table.Header>\n <Table.Body>\n <Table.Row>\n <Table.Cell colSpan={columns?.length || 1}>\n <div\n className=\"proton-DataTable__message-cell\"\n role={isError ? \"alert\" : \"status\"}\n aria-live=\"polite\"\n >\n <Elevation>\n <div className=\"proton-DataTable__empty-cell\">{message}</div>\n </Elevation>\n </div>\n </Table.Cell>\n </Table.Row>\n </Table.Body>\n </Table>\n </div>\n );\n};\n\nDataTable.displayName = \"ProtonUIDataTable\";\n"],"names":["DataTable","columns","data","loading","tombstoneComponent","error","name","onRowClick","emptyMessage","errorMessage","loadingRows","testId","memoize","sortableColumns","sortedBy","sortDirection","onSort","visibleColumns","col","handleSortClick","column","newDirection","getSortState","columnId","jsx","EmptyState","jsxs","Table","_","index","Tombstone","isSortable","sortState","ChevronUp","row","tableRow","DataTableRow","message","isError","Elevation"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DataTable.cjs.js","sources":["../../../../src/components/Table/DataTable/DataTable.tsx"],"sourcesContent":["\"use client\";\n\nimport { AriaAttributes, ReactNode } from \"react\";\nimport { deepEqual } from \"../../../utils/deepEqual\";\n\nimport { Table, TableRowData } from \"../BaseTable/Table\";\nimport { Elevation } from \"../../Elevation/Elevation\";\nimport { Tombstone } from \"../../Tombstone/Tombstone\";\nimport { ChevronUp } from \"../../Icon/IconComponents/ChevronUp\";\nimport { DataTableRow } from \"./DataTableRow\";\n\nimport \"../BaseTable/Table.css\";\nimport \"./DataTable.css\";\n\nexport type SortDirection = \"ASC\" | \"DESC\";\n\ntype SortingConfig =\n | {\n /** When sorting is enabled, all these props must be provided together. */\n sortableColumns: string[];\n sortedBy: string;\n sortDirection: SortDirection;\n onSort: (columnId: string, direction: SortDirection) => void;\n }\n | {\n /** When no sorting is needed, none of these props should be provided */\n sortableColumns?: never;\n sortedBy?: never;\n sortDirection?: never;\n onSort?: never;\n };\n\nexport interface DataTableColumn<T> {\n /** id for the column */\n id: string;\n /** Header text or component */\n header: ReactNode;\n /** Function to render cell content from row data */\n cell: (row: T) => ReactNode;\n /** Whether this column should be hidden */\n isHidden?: boolean;\n}\n\ninterface BaseDataTableProps<T = any> {\n /**\n * Array of column definitions\n * - {@link DataTableColumn}\n */\n columns: DataTableColumn<T>[];\n /**\n * Array of data objects to display. Can be empty array for loading/empty states\n * @default []\n * */\n data?: T[] | null;\n /**\n * Test ID for testing purposes\n * */\n \"data-testid\"?: string;\n /**\n * Error state\n * @default false\n */\n error?: boolean | string;\n /**\n * Custom empty state message\n * @default \"Data Unavailable\"\n */\n emptyMessage?: string;\n /**\n * Custom error message\n * @default \"An error occurred\"\n */\n errorMessage?: string;\n /** Callback when a row is clicked */\n onRowClick?: (row: T) => void;\n /** Loading state */\n loading?: boolean;\n /**\n * Number of skeleton rows to show in loading state\n * @default 5\n */\n loadingRows?: number;\n /**\n * Enable row-level memoization for performance optimization.\n * Uses deepEqual to compare row data. @see {@link deepEqual}\n * @default true\n */\n memoize?: boolean;\n /**\n * Table name/caption for accessibility. Provides essential context for screen readers.\n * */\n name: string;\n /** Optional tombstone component to use when loading */\n tombstoneComponent?: ReactNode;\n}\n\nexport type DataTableProps<T = any> = BaseDataTableProps<T> & SortingConfig;\n\n/**\n * DataTable is a declarative wrapper around the base Table component.\n * API:\n * - {@link DataTableProps}\n * - {@link SortingConfig}\n *\n * @note Row memoization is enabled by default. Rows only re-render when row data or index changes.\n */\nexport const DataTable = <T,>({\n columns,\n data = [],\n loading = false,\n tombstoneComponent,\n error = false,\n name,\n onRowClick,\n emptyMessage = \"Data Unavailable\",\n errorMessage = \"An error occurred\",\n loadingRows = 5,\n \"data-testid\": testId,\n memoize = true,\n sortableColumns = [],\n sortedBy,\n sortDirection,\n onSort,\n}: DataTableProps<T>) => {\n const visibleColumns = columns.filter((col) => !col.isHidden);\n\n const handleSortClick = (column: DataTableColumn<T>) => {\n if (!onSort) return;\n\n const isCurrentlySorted = sortedBy === column.id;\n const newDirection =\n isCurrentlySorted && sortDirection === \"ASC\" ? \"DESC\" : \"ASC\";\n\n onSort(column.id, newDirection);\n };\n\n const getSortState = (columnId: string): AriaAttributes[\"aria-sort\"] => {\n if (sortedBy !== columnId) return \"none\";\n return sortDirection === \"ASC\" ? \"ascending\" : \"descending\";\n };\n\n if (error) {\n return (\n <EmptyState\n columns={visibleColumns}\n message={typeof error === \"string\" ? error : errorMessage}\n name={name}\n testId={testId}\n isError\n />\n );\n }\n\n if (loading) {\n return (\n <div\n className=\"proton-DataTable\"\n data-testid={testId}\n aria-busy=\"true\"\n aria-label={`Loading ${name}...`}\n >\n <Table name={name}>\n <Table.Header>\n {visibleColumns.map((column) => (\n <Table.Column key={column.id} id={column.id}>\n {column.header}\n </Table.Column>\n ))}\n </Table.Header>\n <Table.Body>\n {Array.from({ length: loadingRows }).map((_, index) => (\n <Table.Row key={`loading-${index}`}>\n {visibleColumns.map((column) => (\n <Table.Cell key={column.id}>\n {tombstoneComponent || (\n <Tombstone\n height=\"1rem\"\n width={\n // cascading tombstone widths\n index % 3 === 0\n ? \"80%\"\n : index % 3 === 1\n ? \"60%\"\n : \"90%\"\n }\n />\n )}\n </Table.Cell>\n ))}\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </div>\n );\n }\n\n if (!data || data.length === 0) {\n return (\n <EmptyState\n columns={visibleColumns}\n message={emptyMessage}\n name={name}\n testId={testId}\n />\n );\n }\n\n return (\n <div className=\"proton-DataTable\" data-testid={testId}>\n <Table name={name}>\n <Table.Header>\n {visibleColumns.map((column) => {\n const isSortable = sortableColumns.includes(column.id);\n const sortState = getSortState(column.id);\n\n return (\n <Table.Column\n key={column.id}\n id={column.id}\n {...(isSortable && { \"aria-sort\": sortState })}\n >\n <span className=\"proton-DataTable__header-content\">\n {column.header}\n\n {isSortable && (\n <button\n className=\"proton-DataTable__sort-button\"\n onClick={() => handleSortClick(column)}\n aria-label={`Sort by ${column.header}: ${sortState}`}\n type=\"button\"\n >\n <ChevronUp\n size={12}\n color={\n sortState === \"ascending\"\n ? \"var(--proton-color__primary)\"\n : \"currentColor\"\n }\n />\n </button>\n )}\n </span>\n </Table.Column>\n );\n })}\n </Table.Header>\n <Table.Body>\n {data.map((row, index) => {\n const tableRow = row as TableRowData;\n\n return (\n <DataTableRow\n key={tableRow.key ?? index}\n row={row}\n columns={visibleColumns}\n rowIndex={index}\n onRowClick={onRowClick}\n memoize={memoize}\n dataTestId={tableRow.dataTestId}\n />\n );\n })}\n </Table.Body>\n </Table>\n </div>\n );\n};\n\nconst EmptyState = ({\n columns,\n message,\n name,\n testId,\n isError = false,\n}: {\n columns: DataTableColumn<any>[];\n name: string;\n testId?: string;\n message: string;\n isError?: boolean;\n}) => {\n return (\n <div className=\"proton-DataTable\" data-testid={testId}>\n <Table name={name}>\n <Table.Header>\n {columns.map((column) => (\n <Table.Column key={column.id} id={column.id}>\n {column.header}\n </Table.Column>\n ))}\n </Table.Header>\n <Table.Body>\n <Table.Row>\n <Table.Cell colSpan={columns?.length || 1}>\n <div\n className=\"proton-DataTable__message-cell\"\n role={isError ? \"alert\" : \"status\"}\n aria-live=\"polite\"\n >\n <Elevation>\n <div className=\"proton-DataTable__empty-cell\">{message}</div>\n </Elevation>\n </div>\n </Table.Cell>\n </Table.Row>\n </Table.Body>\n </Table>\n </div>\n );\n};\n\nDataTable.displayName = \"ProtonUIDataTable\";\n"],"names":["DataTable","columns","data","loading","tombstoneComponent","error","name","onRowClick","emptyMessage","errorMessage","loadingRows","testId","memoize","sortableColumns","sortedBy","sortDirection","onSort","visibleColumns","col","handleSortClick","column","newDirection","getSortState","columnId","jsx","EmptyState","jsxs","Table","_","index","Tombstone","isSortable","sortState","ChevronUp","row","tableRow","DataTableRow","message","isError","Elevation"],"mappings":"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"}
|
|
@@ -24,11 +24,11 @@ const A = ({
|
|
|
24
24
|
sortDirection: x,
|
|
25
25
|
onSort: m
|
|
26
26
|
}) => {
|
|
27
|
-
const d = l.filter((r) => !r.isHidden),
|
|
27
|
+
const d = l.filter((r) => !r.isHidden), S = (r) => {
|
|
28
28
|
if (!m) return;
|
|
29
29
|
const i = j === r.id && x === "ASC" ? "DESC" : "ASC";
|
|
30
30
|
m(r.id, i);
|
|
31
|
-
},
|
|
31
|
+
}, D = (r) => j !== r ? "none" : x === "ASC" ? "ascending" : "descending";
|
|
32
32
|
return o ? /* @__PURE__ */ e.jsx(
|
|
33
33
|
b,
|
|
34
34
|
{
|
|
@@ -69,7 +69,7 @@ const A = ({
|
|
|
69
69
|
}
|
|
70
70
|
) : /* @__PURE__ */ e.jsx("div", { className: "proton-DataTable", "data-testid": c, children: /* @__PURE__ */ e.jsxs(a, { name: s, children: [
|
|
71
71
|
/* @__PURE__ */ e.jsx(a.Header, { children: d.map((r) => {
|
|
72
|
-
const t = T.includes(r.id), i =
|
|
72
|
+
const t = T.includes(r.id), i = D(r.id);
|
|
73
73
|
return /* @__PURE__ */ e.jsx(
|
|
74
74
|
a.Column,
|
|
75
75
|
{
|
|
@@ -81,7 +81,7 @@ const A = ({
|
|
|
81
81
|
"button",
|
|
82
82
|
{
|
|
83
83
|
className: "proton-DataTable__sort-button",
|
|
84
|
-
onClick: () =>
|
|
84
|
+
onClick: () => S(r),
|
|
85
85
|
"aria-label": `Sort by ${r.header}: ${i}`,
|
|
86
86
|
type: "button",
|
|
87
87
|
children: /* @__PURE__ */ e.jsx(
|
|
@@ -115,9 +115,9 @@ const A = ({
|
|
|
115
115
|
}) })
|
|
116
116
|
] }) });
|
|
117
117
|
}, b = ({
|
|
118
|
-
columns: l
|
|
118
|
+
columns: l,
|
|
119
119
|
message: n,
|
|
120
|
-
name: h
|
|
120
|
+
name: h,
|
|
121
121
|
testId: p,
|
|
122
122
|
isError: o = !1
|
|
123
123
|
}) => /* @__PURE__ */ e.jsx("div", { className: "proton-DataTable", "data-testid": p, children: /* @__PURE__ */ e.jsxs(a, { name: h, children: [
|