@j2-health/design-system 0.6.3 → 0.6.5

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.
@@ -14,6 +14,30 @@ var getAllOptions = (options) => {
14
14
  if (!options) return [];
15
15
  return options.flatMap((option) => isGroupOption(option) ? option.options : [option]);
16
16
  };
17
+ var byLabel = (a, b) => String(a.label ?? "").localeCompare(String(b.label ?? ""), void 0, {
18
+ numeric: true,
19
+ sensitivity: "base"
20
+ });
21
+ /** One entry per value, the first one seen, sorted by label. */
22
+ var flattenAndSort = (options) => {
23
+ const seen = /* @__PURE__ */ new Set();
24
+ return getAllOptions(options).filter((option) => {
25
+ if (seen.has(option.value)) return false;
26
+ seen.add(option.value);
27
+ return true;
28
+ }).sort(byLabel);
29
+ };
30
+ var withGroupDividers = (options) => {
31
+ let groupsSeen = 0;
32
+ return options.map((option) => {
33
+ if (!isGroupOption(option)) return option;
34
+ groupsSeen += 1;
35
+ return groupsSeen === 1 ? option : {
36
+ ...option,
37
+ className: cx(option.className, SummarizedSelect_module_default.groupDivider)
38
+ };
39
+ });
40
+ };
17
41
  var filterOptions = (options, searchValue) => {
18
42
  if (!options) return [];
19
43
  if (!searchValue) return options;
@@ -35,7 +59,27 @@ var filterOptions = (options, searchValue) => {
35
59
  */
36
60
  var WEIGHT_CLASS = /(^|\s)font-(thin|extralight|light|normal|medium|semibold|bold|extrabold|black|\[\d+\])(\s|$)/;
37
61
  var hasWeightClass = (className) => Boolean(className && WEIGHT_CLASS.test(className));
38
- function SummarizedSelect({ searchPlaceholder, formControlPlaceholder, loading, multiple, value, onChange, options, renderLabel, rootClassName, popupClassName, variant, trigger = "select", triggerWeight, defaultOpen = false, ...props }) {
62
+ /**
63
+ * Puts the option list back at the top each time it opens and each time it is
64
+ * rebuilt for a search. antd scrolls to the selected option from a timeout
65
+ * started in the list's own effect. This wraps the list, so its effect runs
66
+ * after that one and its timeout lands last. It keys off a count of opens, not
67
+ * the open flag: antd does not re-render a closed popup, so the flag it sees
68
+ * can stay `true` from one open to the next.
69
+ */
70
+ var OpenAtTop = ({ openCount, selectRef, children }) => {
71
+ useEffect(() => {
72
+ const timeoutId = setTimeout(() => {
73
+ selectRef.current?.scrollTo({
74
+ index: 0,
75
+ align: "top"
76
+ });
77
+ });
78
+ return () => clearTimeout(timeoutId);
79
+ }, [openCount, selectRef]);
80
+ return children;
81
+ };
82
+ function SummarizedSelect({ searchPlaceholder, formControlPlaceholder, loading, multiple, value, onChange, options, renderLabel, rootClassName, popupClassName, variant, trigger = "select", triggerWeight, defaultOpen = false, flattenOnSearch = false, scrollToSelectedOnOpen = true, groupDividers = false, ...props }) {
39
83
  const isHeadline = variant === "headlined";
40
84
  const isField = variant === "field";
41
85
  const antVariant = isHeadline ? "borderless" : isField ? "outlined" : variant;
@@ -44,6 +88,7 @@ function SummarizedSelect({ searchPlaceholder, formControlPlaceholder, loading,
44
88
  const [focusTrigger, setFocusTrigger] = useState(defaultOpen ? 1 : 0);
45
89
  const [isOpen, setIsOpen] = useState(defaultOpen);
46
90
  const inputRef = useRef(null);
91
+ const selectRef = useRef(null);
47
92
  const measureSpanRef = useRef(null);
48
93
  const [measuredWidth, setMeasuredWidth] = useState();
49
94
  const displayText = useMemo(() => {
@@ -77,8 +122,15 @@ function SummarizedSelect({ searchPlaceholder, formControlPlaceholder, loading,
77
122
  });
78
123
  }, [focusTrigger]);
79
124
  const filteredOptions = useMemo(() => {
80
- return filterOptions(options, searchValue);
81
- }, [searchValue, options]);
125
+ const filtered = filterOptions(options, searchValue);
126
+ if (flattenOnSearch && searchValue) return flattenAndSort(filtered);
127
+ return groupDividers ? withGroupDividers(filtered) : filtered;
128
+ }, [
129
+ searchValue,
130
+ options,
131
+ flattenOnSearch,
132
+ groupDividers
133
+ ]);
82
134
  const flatFilteredOptions = useMemo(() => {
83
135
  return getAllOptions(filteredOptions);
84
136
  }, [filteredOptions]);
@@ -197,7 +249,11 @@ function SummarizedSelect({ searchPlaceholder, formControlPlaceholder, loading,
197
249
  [SummarizedSelect_module_default.headlinedMenuContainer]: isHeadline,
198
250
  [SummarizedSelect_module_default.menuContainerMultiple]: multiple
199
251
  }),
200
- children: /* @__PURE__ */ jsx(Fragment, { children: menu }, searchValue)
252
+ children: /* @__PURE__ */ jsx(Fragment, { children: scrollToSelectedOnOpen ? menu : /* @__PURE__ */ jsx(OpenAtTop, {
253
+ openCount: focusTrigger,
254
+ selectRef,
255
+ children: menu
256
+ }) }, searchValue)
201
257
  }),
202
258
  /* @__PURE__ */ jsx("div", {
203
259
  className: "flex justify-between items-center",
@@ -295,10 +351,13 @@ function SummarizedSelect({ searchPlaceholder, formControlPlaceholder, loading,
295
351
  className: "px-3 py-2 text-sm text-[var(--j2-color-text-secondary)]",
296
352
  children: "No options found"
297
353
  }) : filteredOptions.map((opt) => {
298
- if (isGroupOption(opt)) return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
299
- className: "px-3 pt-2 pb-1 text-xs font-semibold uppercase tracking-wide text-[var(--j2-color-text-tertiary)]",
300
- children: opt.label
301
- }), opt.options.map(renderDropdownOptionRow)] }, `group-${opt.label}`);
354
+ if (isGroupOption(opt)) return /* @__PURE__ */ jsxs("div", {
355
+ className: opt.className,
356
+ children: [/* @__PURE__ */ jsx("div", {
357
+ className: "px-3 pt-2 pb-1 text-xs font-semibold uppercase tracking-wide text-[var(--j2-color-text-tertiary)]",
358
+ children: opt.label
359
+ }), opt.options.map(renderDropdownOptionRow)]
360
+ }, `group-${opt.label}`);
302
361
  return renderDropdownOptionRow(opt);
303
362
  })
304
363
  }),
@@ -354,6 +413,7 @@ function SummarizedSelect({ searchPlaceholder, formControlPlaceholder, loading,
354
413
  },
355
414
  children: displayText
356
415
  }), /* @__PURE__ */ jsx(Select, {
416
+ ref: selectRef,
357
417
  open: isOpen,
358
418
  showSearch: false,
359
419
  style: { width: isField ? "100%" : measuredWidth },
@@ -1 +1 @@
1
- {"version":3,"file":"SummarizedSelect.js","names":["Tag","styles","AntdDropdown","_Fragment"],"sources":["../../../../src/components/select/SummarizedSelect.tsx"],"sourcesContent":["import {\n Dropdown as AntdDropdown,\n Select,\n Spin,\n Input,\n SelectProps,\n InputRef,\n Typography,\n} from 'antd'\nimport { DefaultOptionType } from 'antd/es/select'\nimport { Fragment, useState, useMemo, useRef, useEffect } from 'react'\nimport { LoadingOutlined } from '@ant-design/icons'\nimport { CaretDownIcon, MagnifyingGlassIcon } from '@phosphor-icons/react'\nimport { Tag } from '../tag'\nimport cx from 'classnames'\n\nimport styles from './SummarizedSelect.module.css'\n\ntype Option = DefaultOptionType\ntype OptionWithLogo = Option & {\n logo: React.ReactNode\n}\n\ntype GroupOption = {\n label: string\n options: Option[]\n}\n\nexport type SelectOption = Option | GroupOption | OptionWithLogo\n\nexport type SummarizedSelectVariant =\n SelectProps['variant'] | 'headlined' | 'field'\n\nexport type SummarizedSelectTrigger = 'select' | 'dropdown'\n\ntype BaseProps = Omit<\n SelectProps<string | string[], SelectOption>,\n 'mode' | 'value' | 'onChange' | 'variant'\n> & {\n searchPlaceholder?: string\n formControlPlaceholder?: string\n rootClassName?: string\n popupClassName?: string\n /**\n * Look of the `'select'` trigger.\n * - antd's own variants (`'outlined'`, `'borderless'`, ...): the filter-chip\n * look. It sizes to its label and turns into a filled pill once a\n * multiple select has values.\n * - `'headlined'`: a page-title select.\n * - `'field'`: a plain form field. It fills its container and keeps the\n * same look whatever is selected, so it lines up with the inputs and\n * selects around it in a form row.\n */\n variant?: SummarizedSelectVariant\n /**\n * Shape of the control that opens the popup.\n * - `'select'` (default): antd Select, styled by `variant`.\n * - `'dropdown'`: antd Dropdown with a text target (label + caret), for\n * breadcrumbs and inline switchers. Semibold primary text with a duotone\n * caret. A Tailwind weight utility on `rootClassName` (`font-normal`,\n * `font-[450]`) replaces the default; for any other weight, use\n * `triggerWeight`. Ignores `variant`.\n */\n trigger?: SummarizedSelectTrigger\n /**\n * The `'dropdown'` trigger's font weight, e.g. `400` or `'normal'`.\n * Replaces the semibold default and wins over any class. Use it for a\n * weight `rootClassName` can't express as a Tailwind weight utility.\n */\n triggerWeight?: React.CSSProperties['fontWeight']\n defaultOpen?: boolean\n\n loading?: boolean\n}\n\ntype SingleProps = {\n multiple?: false\n renderLabel?: undefined\n value: string | undefined\n onChange: (newValue: string) => void\n}\n\ntype MultiProps = {\n multiple: true\n renderLabel: (count: number) => string\n value: string[]\n onChange: (newValue: string[]) => void\n}\n\nexport type Props = BaseProps & (SingleProps | MultiProps)\n\nconst isGroupOption = (option: SelectOption): option is GroupOption => {\n return 'options' in option\n}\n\nconst getAllOptions = (options: SelectOption[] | undefined): Option[] => {\n if (!options) return []\n\n return options.flatMap((option) =>\n isGroupOption(option) ? option.options : [option]\n )\n}\n\nconst filterOptions = (\n options: SelectOption[] | undefined,\n searchValue: string\n): SelectOption[] => {\n if (!options) return []\n if (!searchValue) return options\n\n return options\n .map((option) => {\n if (isGroupOption(option)) {\n const filteredSubOptions = option.options.filter((subOption) =>\n subOption.label\n ?.toString()\n .toLowerCase()\n .includes(searchValue.toLowerCase())\n )\n return filteredSubOptions.length > 0\n ? { ...option, options: filteredSubOptions }\n : null\n } else {\n return option.label\n ?.toString()\n .toLowerCase()\n .includes(searchValue.toLowerCase())\n ? option\n : null\n }\n })\n .filter((option): option is SelectOption => option !== null)\n}\n\n/**\n * An unprefixed Tailwind font-weight utility: a named weight (`font-normal`,\n * `font-bold`) or an arbitrary numeric one (`font-[450]`). Arbitrary values\n * must be numeric, since `font-['Inter']` sets the family. Custom weight names\n * can't be told apart from family names, so they need `triggerWeight`.\n */\nconst WEIGHT_CLASS =\n /(^|\\s)font-(thin|extralight|light|normal|medium|semibold|bold|extrabold|black|\\[\\d+\\])(\\s|$)/\n\nconst hasWeightClass = (className?: string) =>\n Boolean(className && WEIGHT_CLASS.test(className))\n\nexport function SummarizedSelect({\n searchPlaceholder,\n formControlPlaceholder,\n loading,\n multiple,\n value,\n onChange,\n options,\n renderLabel,\n rootClassName,\n popupClassName,\n variant,\n trigger = 'select',\n triggerWeight,\n defaultOpen = false,\n ...props\n}: Props) {\n const isHeadline = variant === 'headlined'\n const isField = variant === 'field'\n const antVariant = isHeadline ? 'borderless' : isField ? 'outlined' : variant\n const isChip = !isField && variant !== 'underlined' && !isHeadline\n const [searchValue, setSearchValue] = useState('')\n const [focusTrigger, setFocusTrigger] = useState(defaultOpen ? 1 : 0)\n const [isOpen, setIsOpen] = useState(defaultOpen)\n const inputRef = useRef<InputRef>(null)\n const measureSpanRef = useRef<HTMLSpanElement>(null)\n const [measuredWidth, setMeasuredWidth] = useState<number>()\n\n const displayText = useMemo(() => {\n if (multiple && value.length > 0) {\n return renderLabel(value.length)\n }\n if (!multiple && value) {\n const option = getAllOptions(options).find((opt) => opt.value === value)\n return option ? String(option.label) : String(value)\n }\n return formControlPlaceholder ?? ''\n }, [multiple, value, options, renderLabel, formControlPlaceholder])\n\n useEffect(() => {\n if (!measureSpanRef.current) return\n // padding (22px = 11px each side) + arrow (18px) + border (6px)\n setMeasuredWidth(Math.ceil(measureSpanRef.current.offsetWidth) + 46)\n }, [displayText])\n\n useEffect(() => {\n if (focusTrigger > 0) {\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n setTimeout(() => {\n // `preventScroll`: on first open the popup is still at its initial\n // spot when this runs, and a plain focus scrolls the page to it.\n inputRef.current?.focus({ cursor: 'end', preventScroll: true })\n }, 100)\n })\n })\n }\n }, [focusTrigger])\n\n const filteredOptions = useMemo(() => {\n return filterOptions(options, searchValue)\n }, [searchValue, options])\n\n const flatFilteredOptions = useMemo(() => {\n return getAllOptions(filteredOptions)\n }, [filteredOptions])\n\n const allFlatOptions = useMemo(() => {\n return getAllOptions(options)\n }, [options])\n\n const handleTagClose = (removedValue: string) => {\n if (!multiple) return\n\n onChange(value.filter((x) => x !== removedValue))\n }\n\n const handleToggleAll = () => {\n if (!multiple) return\n\n const allFilteredValues = getAllOptions(filteredOptions).map(\n (opt) => opt.value as string\n )\n const someSelected = allFilteredValues.some((val) => value.includes(val))\n\n if (someSelected) {\n onChange(value.filter((val) => !allFilteredValues.includes(val)))\n }\n }\n\n const handleSelectFirstOption = () => {\n if (flatFilteredOptions.length === 0) return\n\n const firstOption = flatFilteredOptions[0]\n if (!firstOption) return\n\n const optionValue = firstOption.value as string\n\n if (multiple) {\n if (value.includes(optionValue)) {\n onChange(value.filter((v) => v !== optionValue))\n } else {\n onChange([...value, optionValue])\n }\n } else {\n onChange(optionValue)\n handleOpenChange(false)\n }\n }\n\n const handleOptionClick = (optionValue: string) => {\n if (multiple) {\n if (value.includes(optionValue)) {\n onChange(value.filter((v) => v !== optionValue))\n } else {\n onChange([...value, optionValue])\n }\n } else {\n onChange(optionValue)\n handleOpenChange(false)\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n // Allow these navigation keys to bubble up to Select's native keyboard handler\n const navigationKeys = ['ArrowUp', 'ArrowDown']\n\n // Handle Enter - select first filtered option (custom behavior)\n if (e.key === 'Enter') {\n e.preventDefault()\n e.stopPropagation()\n handleSelectFirstOption()\n return\n }\n\n // Handle Escape - close dropdown (custom behavior)\n if (e.key === 'Escape') {\n e.preventDefault()\n e.stopPropagation()\n handleOpenChange(false)\n return\n }\n\n // For arrow keys, prevent cursor movement but allow propagation to Select\n if (navigationKeys.includes(e.key)) {\n e.preventDefault() // Prevents cursor from moving to start/end of input text\n // Do NOT call stopPropagation() - let event bubble to Select component\n return\n }\n\n // For all other keys (including Backspace), stop propagation\n // This prevents backspace from removing tags in multiple mode\n e.stopPropagation()\n }\n\n const optionRender: NonNullable<\n SelectProps<string | string[], SelectOption>['optionRender']\n > = (option) => {\n if ('logo' in option.data && option.data.logo) {\n return (\n <div className=\"flex items-center gap-2\">\n <div className=\"h-4 shrink-0\">{option.data.logo}</div>\n <span className=\"overflow-ellipsis overflow-hidden\">\n {option.label}\n </span>\n </div>\n )\n }\n return <div>{option.label}</div>\n }\n\n const popupRender = (menu: React.ReactElement) => {\n const valueToLabel = (val: string) => {\n const option = allFlatOptions.find((opt) => opt.value === val)\n return option ? (option.label as string) : val\n }\n\n return (\n <div>\n <div className=\"mb-2 px-2 pb-2 border-b -mx-1 mt-1\">\n <Input\n ref={inputRef}\n key={focusTrigger}\n placeholder={searchPlaceholder || 'Search...'}\n value={searchValue}\n onChange={(e) => {\n setSearchValue(e.target.value)\n e.stopPropagation()\n e.preventDefault()\n }}\n onKeyDown={handleKeyDown}\n onClick={(e) => e.stopPropagation()}\n prefix={\n <MagnifyingGlassIcon\n size={16}\n className=\"text-j2-text-placeholder\"\n />\n }\n allowClear\n />\n </div>\n {multiple && value.length > 0 ? (\n <div className=\"px-2 pb-2\">\n <div className=\"flex flex-wrap gap-y-1\">\n {(value as string[]).map((value) => (\n <Tag\n className=\"opacity-100 z-10 flex max-w-full\"\n key={value}\n status=\"default\"\n closable\n onClose={() => handleTagClose(value)}\n >\n <span\n className=\"overflow-ellipsis overflow-hidden\"\n title={valueToLabel(value)}\n >\n {valueToLabel(value)}\n </span>\n </Tag>\n ))}\n </div>\n </div>\n ) : null}\n <div\n className={cx(styles.menuContainer, 'rounded-lg', {\n [styles.headlinedMenuContainer]: isHeadline,\n [styles.menuContainerMultiple]: multiple,\n })}\n >\n {/* Keyed on the search so antd rebuilds its option list per\n keystroke. Focusing the search input blurs the Select, antd\n starts a close, cancels it because focus stayed in the popup,\n and never clears its `lockOptions` flag -- a locked list keeps\n showing the options it had when the popup opened. */}\n <Fragment key={searchValue}>{menu}</Fragment>\n </div>\n <div className=\"flex justify-between items-center\">\n {multiple && (\n <div className=\"w-full mt-1 pt-1 border-t border-j2-border-secondary\">\n <div\n aria-selected=\"false\"\n className={cx(\n 'ant-select-item ant-select-item-option w-full',\n styles.clearAllButton\n )}\n title=\"Clear all\"\n onClick={handleToggleAll}\n >\n <div className=\"ant-select-item-option-content text-center font-semibold\">\n Clear all\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n )\n }\n\n const handleOpenChange = (open: boolean) => {\n setIsOpen(open)\n if (open) {\n // Trigger focus by updating the counter\n setFocusTrigger((prev) => prev + 1)\n } else {\n setSearchValue('')\n }\n }\n\n const renderDropdownOptionRow = (option: Option) => {\n const optionValue = option.value as string\n const isSelected = multiple\n ? value.includes(optionValue)\n : value === optionValue\n const hasLogo = 'logo' in option && (option as OptionWithLogo).logo\n return (\n <div\n key={optionValue}\n role=\"option\"\n aria-selected={isSelected}\n onClick={() => handleOptionClick(optionValue)}\n className={cx(\n 'px-3 py-1.5 rounded cursor-pointer text-sm',\n isSelected\n ? 'bg-[var(--j2-color-primary-bg-hover)] font-semibold text-[var(--j2-color-primary)] hover:bg-[var(--j2-color-primary-bg-hover)]'\n : 'hover:bg-[var(--j2-color-bg-hover)]'\n )}\n >\n {hasLogo ? (\n <div className=\"flex items-center gap-2\">\n <div className=\"h-4 shrink-0\">\n {(option as OptionWithLogo).logo}\n </div>\n <span className=\"overflow-hidden overflow-ellipsis\">\n {option.label}\n </span>\n </div>\n ) : (\n option.label\n )}\n </div>\n )\n }\n\n const dropdownPopupRender = () => {\n const valueToLabel = (val: string) => {\n const option = allFlatOptions.find((opt) => opt.value === val)\n return option ? (option.label as string) : val\n }\n\n return (\n <div className=\"bg-white rounded-lg shadow-md p-2 min-w-[240px]\">\n <div className=\"pb-2 border-b border-j2-border-secondary\">\n <Input\n ref={inputRef}\n key={focusTrigger}\n placeholder={searchPlaceholder || 'Search...'}\n value={searchValue}\n onChange={(e) => {\n setSearchValue(e.target.value)\n e.stopPropagation()\n }}\n onKeyDown={handleKeyDown}\n onClick={(e) => e.stopPropagation()}\n prefix={\n <MagnifyingGlassIcon\n size={16}\n className=\"text-j2-text-placeholder\"\n />\n }\n allowClear\n />\n </div>\n {multiple && value.length > 0 && (\n <div className=\"px-1 pt-2\">\n <div className=\"flex flex-wrap gap-y-1\">\n {(value as string[]).map((v) => (\n <Tag\n className=\"opacity-100 z-10 flex max-w-full\"\n key={v}\n status=\"default\"\n closable\n onClose={() => handleTagClose(v)}\n >\n <span\n className=\"overflow-ellipsis overflow-hidden\"\n title={valueToLabel(v)}\n >\n {valueToLabel(v)}\n </span>\n </Tag>\n ))}\n </div>\n </div>\n )}\n <div\n className=\"max-h-72 overflow-y-auto py-1\"\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n >\n {filteredOptions.length === 0 ? (\n <div className=\"px-3 py-2 text-sm text-[var(--j2-color-text-secondary)]\">\n No options found\n </div>\n ) : (\n filteredOptions.map((opt) => {\n if (isGroupOption(opt)) {\n return (\n <div key={`group-${opt.label}`}>\n <div className=\"px-3 pt-2 pb-1 text-xs font-semibold uppercase tracking-wide text-[var(--j2-color-text-tertiary)]\">\n {opt.label}\n </div>\n {opt.options.map(renderDropdownOptionRow)}\n </div>\n )\n }\n return renderDropdownOptionRow(opt)\n })\n )}\n </div>\n {multiple && value.length > 0 && (\n <div className=\"mt-1 pt-1 border-t border-j2-border-secondary\">\n <div\n role=\"button\"\n aria-label=\"Clear all\"\n title=\"Clear all\"\n onClick={handleToggleAll}\n className={cx(\n 'text-center font-semibold text-sm py-1.5 rounded cursor-pointer',\n styles.clearAllButton\n )}\n >\n Clear all\n </div>\n </div>\n )}\n </div>\n )\n }\n\n if (trigger === 'dropdown') {\n const hasSelection = multiple ? value.length > 0 : Boolean(value)\n const triggerContent = (\n <span className=\"inline-flex items-center gap-1.5\">\n {hasSelection ? displayText : (formControlPlaceholder ?? 'Select')}\n {loading ? (\n <Spin\n indicator={<LoadingOutlined spin />}\n size=\"small\"\n data-testid=\"loading-spinner\"\n />\n ) : (\n <CaretDownIcon weight=\"duotone\" data-testid=\"caret-down\" />\n )}\n </span>\n )\n\n return (\n <AntdDropdown\n open={isOpen}\n onOpenChange={handleOpenChange}\n trigger={['click']}\n disabled={props.disabled}\n popupRender={dropdownPopupRender}\n >\n <Typography.Link\n disabled={props.disabled}\n className={cx(\n 'inline-flex',\n styles.dropdownTrigger,\n triggerWeight === undefined &&\n !hasWeightClass(rootClassName) &&\n 'font-semibold',\n rootClassName\n )}\n style={\n triggerWeight === undefined\n ? undefined\n : { fontWeight: triggerWeight }\n }\n >\n {triggerContent}\n </Typography.Link>\n </AntdDropdown>\n )\n }\n\n return (\n <>\n <span\n ref={measureSpanRef}\n aria-hidden\n style={{\n position: 'absolute',\n visibility: 'hidden',\n whiteSpace: 'nowrap',\n fontSize: 'inherit',\n }}\n >\n {displayText}\n </span>\n <Select<string | string[], SelectOption>\n open={isOpen}\n showSearch={false}\n style={{ width: isField ? '100%' : measuredWidth }}\n suffixIcon={\n loading ? (\n <Spin\n indicator={<LoadingOutlined spin />}\n size=\"small\"\n data-testid=\"loading-spinner\"\n />\n ) : (\n <CaretDownIcon size={14} data-testid=\"caret-down\" />\n )\n }\n placeholder={formControlPlaceholder}\n mode={multiple ? 'multiple' : undefined}\n value={value}\n maxTagCount={0}\n maxTagPlaceholder={multiple ? () => renderLabel(value.length) : value}\n options={filteredOptions}\n onChange={(val) => {\n if (multiple) {\n if (Array.isArray(val)) {\n onChange(val)\n } else {\n throw new Error('Value should be an array in multiple mode')\n }\n } else {\n if (typeof val === 'string') {\n onChange(val)\n } else {\n throw new Error(\n 'Value should be a string in single selection mode'\n )\n }\n }\n }}\n popupRender={popupRender}\n optionRender={optionRender}\n onOpenChange={handleOpenChange}\n classNames={{\n root: cx(rootClassName, styles.summarizedSelect, {\n [styles.hemisphericSelect]: isChip,\n [styles.isActive]: isChip && multiple && value.length > 0,\n [styles.headlinedSelect]: isHeadline,\n [styles.fieldSelect]: isField,\n }),\n popup: { root: popupClassName },\n }}\n variant={antVariant}\n {...props}\n />\n </>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"SummarizedSelect.js","names":["styles","Tag","AntdDropdown","_Fragment"],"sources":["../../../../src/components/select/SummarizedSelect.tsx"],"sourcesContent":["import {\n Dropdown as AntdDropdown,\n Select,\n Spin,\n Input,\n SelectProps,\n InputRef,\n Typography,\n} from 'antd'\nimport { DefaultOptionType, type RefSelectProps } from 'antd/es/select'\nimport { Fragment, useState, useMemo, useRef, useEffect } from 'react'\nimport { LoadingOutlined } from '@ant-design/icons'\nimport { CaretDownIcon, MagnifyingGlassIcon } from '@phosphor-icons/react'\nimport { Tag } from '../tag'\nimport cx from 'classnames'\n\nimport styles from './SummarizedSelect.module.css'\n\ntype Option = DefaultOptionType\ntype OptionWithLogo = Option & {\n logo: React.ReactNode\n}\n\ntype GroupOption = {\n label: string\n options: Option[]\n className?: string\n}\n\nexport type SelectOption = Option | GroupOption | OptionWithLogo\n\nexport type SummarizedSelectVariant =\n SelectProps['variant'] | 'headlined' | 'field'\n\nexport type SummarizedSelectTrigger = 'select' | 'dropdown'\n\ntype BaseProps = Omit<\n SelectProps<string | string[], SelectOption>,\n 'mode' | 'value' | 'onChange' | 'variant'\n> & {\n searchPlaceholder?: string\n formControlPlaceholder?: string\n rootClassName?: string\n popupClassName?: string\n /**\n * Look of the `'select'` trigger.\n * - antd's own variants (`'outlined'`, `'borderless'`, ...): the filter-chip\n * look. It sizes to its label and turns into a filled pill once a\n * multiple select has values.\n * - `'headlined'`: a page-title select.\n * - `'field'`: a plain form field. It fills its container and keeps the\n * same look whatever is selected, so it lines up with the inputs and\n * selects around it in a form row.\n */\n variant?: SummarizedSelectVariant\n /**\n * Shape of the control that opens the popup.\n * - `'select'` (default): antd Select, styled by `variant`.\n * - `'dropdown'`: antd Dropdown with a text target (label + caret), for\n * breadcrumbs and inline switchers. Semibold primary text with a duotone\n * caret. A Tailwind weight utility on `rootClassName` (`font-normal`,\n * `font-[450]`) replaces the default; for any other weight, use\n * `triggerWeight`. Ignores `variant`.\n */\n trigger?: SummarizedSelectTrigger\n /**\n * The `'dropdown'` trigger's font weight, e.g. `400` or `'normal'`.\n * Replaces the semibold default and wins over any class. Use it for a\n * weight `rootClassName` can't express as a Tailwind weight utility.\n */\n triggerWeight?: React.CSSProperties['fontWeight']\n defaultOpen?: boolean\n /**\n * While searching, list the matches as one list sorted by label: groups are\n * dropped, and a value that appears in more than one group shows once. Lets\n * a list that repeats options in a shortcut group (Recent, say) above the\n * full list search as a single list. Groups come back when the search is\n * cleared.\n */\n flattenOnSearch?: boolean\n /**\n * `false` opens the `'select'` trigger's list at the top every time instead\n * of scrolled to the selected option, for a list whose first rows matter\n * more than where the selection is. The `'dropdown'` trigger always opens\n * at the top.\n */\n scrollToSelectedOnOpen?: boolean\n /** A line between option groups, above the title of every group after the first. */\n groupDividers?: boolean\n\n loading?: boolean\n}\n\ntype SingleProps = {\n multiple?: false\n renderLabel?: undefined\n value: string | undefined\n onChange: (newValue: string) => void\n}\n\ntype MultiProps = {\n multiple: true\n renderLabel: (count: number) => string\n value: string[]\n onChange: (newValue: string[]) => void\n}\n\nexport type Props = BaseProps & (SingleProps | MultiProps)\n\nconst isGroupOption = (option: SelectOption): option is GroupOption => {\n return 'options' in option\n}\n\nconst getAllOptions = (options: SelectOption[] | undefined): Option[] => {\n if (!options) return []\n\n return options.flatMap((option) =>\n isGroupOption(option) ? option.options : [option]\n )\n}\n\nconst byLabel = (a: Option, b: Option) =>\n String(a.label ?? '').localeCompare(String(b.label ?? ''), undefined, {\n numeric: true,\n sensitivity: 'base',\n })\n\n/** One entry per value, the first one seen, sorted by label. */\nconst flattenAndSort = (options: SelectOption[]): Option[] => {\n const seen = new Set<unknown>()\n return getAllOptions(options)\n .filter((option) => {\n if (seen.has(option.value)) return false\n seen.add(option.value)\n return true\n })\n .sort(byLabel)\n}\n\nconst withGroupDividers = (options: SelectOption[]): SelectOption[] => {\n let groupsSeen = 0\n return options.map((option) => {\n if (!isGroupOption(option)) return option\n groupsSeen += 1\n return groupsSeen === 1\n ? option\n : {\n ...option,\n className: cx(option.className, styles.groupDivider),\n }\n })\n}\n\nconst filterOptions = (\n options: SelectOption[] | undefined,\n searchValue: string\n): SelectOption[] => {\n if (!options) return []\n if (!searchValue) return options\n\n return options\n .map((option) => {\n if (isGroupOption(option)) {\n const filteredSubOptions = option.options.filter((subOption) =>\n subOption.label\n ?.toString()\n .toLowerCase()\n .includes(searchValue.toLowerCase())\n )\n return filteredSubOptions.length > 0\n ? { ...option, options: filteredSubOptions }\n : null\n } else {\n return option.label\n ?.toString()\n .toLowerCase()\n .includes(searchValue.toLowerCase())\n ? option\n : null\n }\n })\n .filter((option): option is SelectOption => option !== null)\n}\n\n/**\n * An unprefixed Tailwind font-weight utility: a named weight (`font-normal`,\n * `font-bold`) or an arbitrary numeric one (`font-[450]`). Arbitrary values\n * must be numeric, since `font-['Inter']` sets the family. Custom weight names\n * can't be told apart from family names, so they need `triggerWeight`.\n */\nconst WEIGHT_CLASS =\n /(^|\\s)font-(thin|extralight|light|normal|medium|semibold|bold|extrabold|black|\\[\\d+\\])(\\s|$)/\n\nconst hasWeightClass = (className?: string) =>\n Boolean(className && WEIGHT_CLASS.test(className))\n\n/**\n * Puts the option list back at the top each time it opens and each time it is\n * rebuilt for a search. antd scrolls to the selected option from a timeout\n * started in the list's own effect. This wraps the list, so its effect runs\n * after that one and its timeout lands last. It keys off a count of opens, not\n * the open flag: antd does not re-render a closed popup, so the flag it sees\n * can stay `true` from one open to the next.\n */\nconst OpenAtTop = ({\n openCount,\n selectRef,\n children,\n}: {\n openCount: number\n selectRef: React.RefObject<RefSelectProps | null>\n children: React.ReactElement\n}) => {\n useEffect(() => {\n const timeoutId = setTimeout(() => {\n selectRef.current?.scrollTo({ index: 0, align: 'top' })\n })\n return () => clearTimeout(timeoutId)\n }, [openCount, selectRef])\n return children\n}\n\nexport function SummarizedSelect({\n searchPlaceholder,\n formControlPlaceholder,\n loading,\n multiple,\n value,\n onChange,\n options,\n renderLabel,\n rootClassName,\n popupClassName,\n variant,\n trigger = 'select',\n triggerWeight,\n defaultOpen = false,\n flattenOnSearch = false,\n scrollToSelectedOnOpen = true,\n groupDividers = false,\n ...props\n}: Props) {\n const isHeadline = variant === 'headlined'\n const isField = variant === 'field'\n const antVariant = isHeadline ? 'borderless' : isField ? 'outlined' : variant\n const isChip = !isField && variant !== 'underlined' && !isHeadline\n const [searchValue, setSearchValue] = useState('')\n const [focusTrigger, setFocusTrigger] = useState(defaultOpen ? 1 : 0)\n const [isOpen, setIsOpen] = useState(defaultOpen)\n const inputRef = useRef<InputRef>(null)\n const selectRef = useRef<RefSelectProps>(null)\n const measureSpanRef = useRef<HTMLSpanElement>(null)\n const [measuredWidth, setMeasuredWidth] = useState<number>()\n\n const displayText = useMemo(() => {\n if (multiple && value.length > 0) {\n return renderLabel(value.length)\n }\n if (!multiple && value) {\n const option = getAllOptions(options).find((opt) => opt.value === value)\n return option ? String(option.label) : String(value)\n }\n return formControlPlaceholder ?? ''\n }, [multiple, value, options, renderLabel, formControlPlaceholder])\n\n useEffect(() => {\n if (!measureSpanRef.current) return\n // padding (22px = 11px each side) + arrow (18px) + border (6px)\n setMeasuredWidth(Math.ceil(measureSpanRef.current.offsetWidth) + 46)\n }, [displayText])\n\n useEffect(() => {\n if (focusTrigger > 0) {\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n setTimeout(() => {\n // `preventScroll`: on first open the popup is still at its initial\n // spot when this runs, and a plain focus scrolls the page to it.\n inputRef.current?.focus({ cursor: 'end', preventScroll: true })\n }, 100)\n })\n })\n }\n }, [focusTrigger])\n\n const filteredOptions = useMemo(() => {\n const filtered = filterOptions(options, searchValue)\n if (flattenOnSearch && searchValue) return flattenAndSort(filtered)\n return groupDividers ? withGroupDividers(filtered) : filtered\n }, [searchValue, options, flattenOnSearch, groupDividers])\n\n const flatFilteredOptions = useMemo(() => {\n return getAllOptions(filteredOptions)\n }, [filteredOptions])\n\n const allFlatOptions = useMemo(() => {\n return getAllOptions(options)\n }, [options])\n\n const handleTagClose = (removedValue: string) => {\n if (!multiple) return\n\n onChange(value.filter((x) => x !== removedValue))\n }\n\n const handleToggleAll = () => {\n if (!multiple) return\n\n const allFilteredValues = getAllOptions(filteredOptions).map(\n (opt) => opt.value as string\n )\n const someSelected = allFilteredValues.some((val) => value.includes(val))\n\n if (someSelected) {\n onChange(value.filter((val) => !allFilteredValues.includes(val)))\n }\n }\n\n const handleSelectFirstOption = () => {\n if (flatFilteredOptions.length === 0) return\n\n const firstOption = flatFilteredOptions[0]\n if (!firstOption) return\n\n const optionValue = firstOption.value as string\n\n if (multiple) {\n if (value.includes(optionValue)) {\n onChange(value.filter((v) => v !== optionValue))\n } else {\n onChange([...value, optionValue])\n }\n } else {\n onChange(optionValue)\n handleOpenChange(false)\n }\n }\n\n const handleOptionClick = (optionValue: string) => {\n if (multiple) {\n if (value.includes(optionValue)) {\n onChange(value.filter((v) => v !== optionValue))\n } else {\n onChange([...value, optionValue])\n }\n } else {\n onChange(optionValue)\n handleOpenChange(false)\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n // Allow these navigation keys to bubble up to Select's native keyboard handler\n const navigationKeys = ['ArrowUp', 'ArrowDown']\n\n // Handle Enter - select first filtered option (custom behavior)\n if (e.key === 'Enter') {\n e.preventDefault()\n e.stopPropagation()\n handleSelectFirstOption()\n return\n }\n\n // Handle Escape - close dropdown (custom behavior)\n if (e.key === 'Escape') {\n e.preventDefault()\n e.stopPropagation()\n handleOpenChange(false)\n return\n }\n\n // For arrow keys, prevent cursor movement but allow propagation to Select\n if (navigationKeys.includes(e.key)) {\n e.preventDefault() // Prevents cursor from moving to start/end of input text\n // Do NOT call stopPropagation() - let event bubble to Select component\n return\n }\n\n // For all other keys (including Backspace), stop propagation\n // This prevents backspace from removing tags in multiple mode\n e.stopPropagation()\n }\n\n const optionRender: NonNullable<\n SelectProps<string | string[], SelectOption>['optionRender']\n > = (option) => {\n if ('logo' in option.data && option.data.logo) {\n return (\n <div className=\"flex items-center gap-2\">\n <div className=\"h-4 shrink-0\">{option.data.logo}</div>\n <span className=\"overflow-ellipsis overflow-hidden\">\n {option.label}\n </span>\n </div>\n )\n }\n return <div>{option.label}</div>\n }\n\n const popupRender = (menu: React.ReactElement) => {\n const valueToLabel = (val: string) => {\n const option = allFlatOptions.find((opt) => opt.value === val)\n return option ? (option.label as string) : val\n }\n\n return (\n <div>\n <div className=\"mb-2 px-2 pb-2 border-b -mx-1 mt-1\">\n <Input\n ref={inputRef}\n key={focusTrigger}\n placeholder={searchPlaceholder || 'Search...'}\n value={searchValue}\n onChange={(e) => {\n setSearchValue(e.target.value)\n e.stopPropagation()\n e.preventDefault()\n }}\n onKeyDown={handleKeyDown}\n onClick={(e) => e.stopPropagation()}\n prefix={\n <MagnifyingGlassIcon\n size={16}\n className=\"text-j2-text-placeholder\"\n />\n }\n allowClear\n />\n </div>\n {multiple && value.length > 0 ? (\n <div className=\"px-2 pb-2\">\n <div className=\"flex flex-wrap gap-y-1\">\n {(value as string[]).map((value) => (\n <Tag\n className=\"opacity-100 z-10 flex max-w-full\"\n key={value}\n status=\"default\"\n closable\n onClose={() => handleTagClose(value)}\n >\n <span\n className=\"overflow-ellipsis overflow-hidden\"\n title={valueToLabel(value)}\n >\n {valueToLabel(value)}\n </span>\n </Tag>\n ))}\n </div>\n </div>\n ) : null}\n <div\n className={cx(styles.menuContainer, 'rounded-lg', {\n [styles.headlinedMenuContainer]: isHeadline,\n [styles.menuContainerMultiple]: multiple,\n })}\n >\n {/* Keyed on the search so antd rebuilds its option list per\n keystroke. Focusing the search input blurs the Select, antd\n starts a close, cancels it because focus stayed in the popup,\n and never clears its `lockOptions` flag -- a locked list keeps\n showing the options it had when the popup opened. */}\n <Fragment key={searchValue}>\n {scrollToSelectedOnOpen ? (\n menu\n ) : (\n <OpenAtTop openCount={focusTrigger} selectRef={selectRef}>\n {menu}\n </OpenAtTop>\n )}\n </Fragment>\n </div>\n <div className=\"flex justify-between items-center\">\n {multiple && (\n <div className=\"w-full mt-1 pt-1 border-t border-j2-border-secondary\">\n <div\n aria-selected=\"false\"\n className={cx(\n 'ant-select-item ant-select-item-option w-full',\n styles.clearAllButton\n )}\n title=\"Clear all\"\n onClick={handleToggleAll}\n >\n <div className=\"ant-select-item-option-content text-center font-semibold\">\n Clear all\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n )\n }\n\n const handleOpenChange = (open: boolean) => {\n setIsOpen(open)\n if (open) {\n // Trigger focus by updating the counter\n setFocusTrigger((prev) => prev + 1)\n } else {\n setSearchValue('')\n }\n }\n\n const renderDropdownOptionRow = (option: Option) => {\n const optionValue = option.value as string\n const isSelected = multiple\n ? value.includes(optionValue)\n : value === optionValue\n const hasLogo = 'logo' in option && (option as OptionWithLogo).logo\n return (\n <div\n key={optionValue}\n role=\"option\"\n aria-selected={isSelected}\n onClick={() => handleOptionClick(optionValue)}\n className={cx(\n 'px-3 py-1.5 rounded cursor-pointer text-sm',\n isSelected\n ? 'bg-[var(--j2-color-primary-bg-hover)] font-semibold text-[var(--j2-color-primary)] hover:bg-[var(--j2-color-primary-bg-hover)]'\n : 'hover:bg-[var(--j2-color-bg-hover)]'\n )}\n >\n {hasLogo ? (\n <div className=\"flex items-center gap-2\">\n <div className=\"h-4 shrink-0\">\n {(option as OptionWithLogo).logo}\n </div>\n <span className=\"overflow-hidden overflow-ellipsis\">\n {option.label}\n </span>\n </div>\n ) : (\n option.label\n )}\n </div>\n )\n }\n\n const dropdownPopupRender = () => {\n const valueToLabel = (val: string) => {\n const option = allFlatOptions.find((opt) => opt.value === val)\n return option ? (option.label as string) : val\n }\n\n return (\n <div className=\"bg-white rounded-lg shadow-md p-2 min-w-[240px]\">\n <div className=\"pb-2 border-b border-j2-border-secondary\">\n <Input\n ref={inputRef}\n key={focusTrigger}\n placeholder={searchPlaceholder || 'Search...'}\n value={searchValue}\n onChange={(e) => {\n setSearchValue(e.target.value)\n e.stopPropagation()\n }}\n onKeyDown={handleKeyDown}\n onClick={(e) => e.stopPropagation()}\n prefix={\n <MagnifyingGlassIcon\n size={16}\n className=\"text-j2-text-placeholder\"\n />\n }\n allowClear\n />\n </div>\n {multiple && value.length > 0 && (\n <div className=\"px-1 pt-2\">\n <div className=\"flex flex-wrap gap-y-1\">\n {(value as string[]).map((v) => (\n <Tag\n className=\"opacity-100 z-10 flex max-w-full\"\n key={v}\n status=\"default\"\n closable\n onClose={() => handleTagClose(v)}\n >\n <span\n className=\"overflow-ellipsis overflow-hidden\"\n title={valueToLabel(v)}\n >\n {valueToLabel(v)}\n </span>\n </Tag>\n ))}\n </div>\n </div>\n )}\n <div\n className=\"max-h-72 overflow-y-auto py-1\"\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n >\n {filteredOptions.length === 0 ? (\n <div className=\"px-3 py-2 text-sm text-[var(--j2-color-text-secondary)]\">\n No options found\n </div>\n ) : (\n filteredOptions.map((opt) => {\n if (isGroupOption(opt)) {\n return (\n <div key={`group-${opt.label}`} className={opt.className}>\n <div className=\"px-3 pt-2 pb-1 text-xs font-semibold uppercase tracking-wide text-[var(--j2-color-text-tertiary)]\">\n {opt.label}\n </div>\n {opt.options.map(renderDropdownOptionRow)}\n </div>\n )\n }\n return renderDropdownOptionRow(opt)\n })\n )}\n </div>\n {multiple && value.length > 0 && (\n <div className=\"mt-1 pt-1 border-t border-j2-border-secondary\">\n <div\n role=\"button\"\n aria-label=\"Clear all\"\n title=\"Clear all\"\n onClick={handleToggleAll}\n className={cx(\n 'text-center font-semibold text-sm py-1.5 rounded cursor-pointer',\n styles.clearAllButton\n )}\n >\n Clear all\n </div>\n </div>\n )}\n </div>\n )\n }\n\n if (trigger === 'dropdown') {\n const hasSelection = multiple ? value.length > 0 : Boolean(value)\n const triggerContent = (\n <span className=\"inline-flex items-center gap-1.5\">\n {hasSelection ? displayText : (formControlPlaceholder ?? 'Select')}\n {loading ? (\n <Spin\n indicator={<LoadingOutlined spin />}\n size=\"small\"\n data-testid=\"loading-spinner\"\n />\n ) : (\n <CaretDownIcon weight=\"duotone\" data-testid=\"caret-down\" />\n )}\n </span>\n )\n\n return (\n <AntdDropdown\n open={isOpen}\n onOpenChange={handleOpenChange}\n trigger={['click']}\n disabled={props.disabled}\n popupRender={dropdownPopupRender}\n >\n <Typography.Link\n disabled={props.disabled}\n className={cx(\n 'inline-flex',\n styles.dropdownTrigger,\n triggerWeight === undefined &&\n !hasWeightClass(rootClassName) &&\n 'font-semibold',\n rootClassName\n )}\n style={\n triggerWeight === undefined\n ? undefined\n : { fontWeight: triggerWeight }\n }\n >\n {triggerContent}\n </Typography.Link>\n </AntdDropdown>\n )\n }\n\n return (\n <>\n <span\n ref={measureSpanRef}\n aria-hidden\n style={{\n position: 'absolute',\n visibility: 'hidden',\n whiteSpace: 'nowrap',\n fontSize: 'inherit',\n }}\n >\n {displayText}\n </span>\n <Select<string | string[], SelectOption>\n ref={selectRef}\n open={isOpen}\n showSearch={false}\n style={{ width: isField ? '100%' : measuredWidth }}\n suffixIcon={\n loading ? (\n <Spin\n indicator={<LoadingOutlined spin />}\n size=\"small\"\n data-testid=\"loading-spinner\"\n />\n ) : (\n <CaretDownIcon size={14} data-testid=\"caret-down\" />\n )\n }\n placeholder={formControlPlaceholder}\n mode={multiple ? 'multiple' : undefined}\n value={value}\n maxTagCount={0}\n maxTagPlaceholder={multiple ? () => renderLabel(value.length) : value}\n options={filteredOptions}\n onChange={(val) => {\n if (multiple) {\n if (Array.isArray(val)) {\n onChange(val)\n } else {\n throw new Error('Value should be an array in multiple mode')\n }\n } else {\n if (typeof val === 'string') {\n onChange(val)\n } else {\n throw new Error(\n 'Value should be a string in single selection mode'\n )\n }\n }\n }}\n popupRender={popupRender}\n optionRender={optionRender}\n onOpenChange={handleOpenChange}\n classNames={{\n root: cx(rootClassName, styles.summarizedSelect, {\n [styles.hemisphericSelect]: isChip,\n [styles.isActive]: isChip && multiple && value.length > 0,\n [styles.headlinedSelect]: isHeadline,\n [styles.fieldSelect]: isField,\n }),\n popup: { root: popupClassName },\n }}\n variant={antVariant}\n {...props}\n />\n </>\n )\n}\n"],"mappings":"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"}
@@ -1,14 +1,15 @@
1
1
  //#region src/components/select/SummarizedSelect.module.css
2
- var hemisphericSelect = "_hemisphericSelect_3wupe_1";
3
- var summarizedSelect = "_summarizedSelect_3wupe_9";
4
- var isActive = "_isActive_3wupe_46";
5
- var menuContainer = "_menuContainer_3wupe_58";
6
- var menuContainerMultiple = "_menuContainerMultiple_3wupe_68";
7
- var headlinedSelect = "_headlinedSelect_3wupe_83";
8
- var headlinedMenuContainer = "_headlinedMenuContainer_3wupe_135";
9
- var clearAllButton = "_clearAllButton_3wupe_146";
10
- var dropdownTrigger = "_dropdownTrigger_3wupe_165";
11
- var fieldSelect = "_fieldSelect_3wupe_186";
2
+ var hemisphericSelect = "_hemisphericSelect_1pxzv_1";
3
+ var summarizedSelect = "_summarizedSelect_1pxzv_9";
4
+ var isActive = "_isActive_1pxzv_46";
5
+ var menuContainer = "_menuContainer_1pxzv_58";
6
+ var menuContainerMultiple = "_menuContainerMultiple_1pxzv_68";
7
+ var headlinedSelect = "_headlinedSelect_1pxzv_83";
8
+ var headlinedMenuContainer = "_headlinedMenuContainer_1pxzv_135";
9
+ var clearAllButton = "_clearAllButton_1pxzv_146";
10
+ var dropdownTrigger = "_dropdownTrigger_1pxzv_165";
11
+ var fieldSelect = "_fieldSelect_1pxzv_186";
12
+ var groupDivider = "_groupDivider_1pxzv_191";
12
13
  var SummarizedSelect_module_default = {
13
14
  hemisphericSelect,
14
15
  summarizedSelect,
@@ -19,13 +20,15 @@ var SummarizedSelect_module_default = {
19
20
  headlinedMenuContainer,
20
21
  clearAllButton,
21
22
  dropdownTrigger,
22
- fieldSelect
23
+ fieldSelect,
24
+ groupDivider
23
25
  };
24
26
  //#endregion
25
27
  exports.clearAllButton = clearAllButton;
26
28
  exports.default = SummarizedSelect_module_default;
27
29
  exports.dropdownTrigger = dropdownTrigger;
28
30
  exports.fieldSelect = fieldSelect;
31
+ exports.groupDivider = groupDivider;
29
32
  exports.headlinedMenuContainer = headlinedMenuContainer;
30
33
  exports.headlinedSelect = headlinedSelect;
31
34
  exports.hemisphericSelect = hemisphericSelect;
@@ -1 +1 @@
1
- {"version":3,"file":"SummarizedSelect.module.css.cjs","names":[],"sources":["../../../../src/components/select/SummarizedSelect.module.css"],"sourcesContent":[".hemisphericSelect {\n border-radius: 9999px !important;\n\n :global(.ant-select-placeholder) {\n color: var(--j2-color-primary) !important;\n }\n}\n\n.summarizedSelect {\n :global(.ant-select-suffix) {\n color: var(--j2-color-primary);\n }\n\n :global(.ant-select-selection-item) {\n background: none !important;\n border: none !important;\n padding-inline-end: 0 !important;\n margin-inline-end: 0 !important;\n }\n\n :global(.ant-select-selection-item-content) {\n margin-inline-end: 0 !important;\n }\n\n :global(.ant-select-content-item-rest) {\n max-width: 100%;\n }\n\n :global(.ant-select-content-item-suffix) {\n position: absolute;\n width: 1px;\n }\n\n /* antd 6 sizes a multiple select from its in-flow items. With the suffix\n (search input) and the placeholder both absolute, an empty select\n collapses to the font size (18px tall). Hold the row at one item's\n height, which the search input supplied before it was taken out of flow. */\n &:global(.ant-select-multiple) :global(.ant-select-content) {\n min-height: calc(\n var(--ant-select-multi-item-height, 24px) +\n var(--ant-select-internal_fixed_item_margin, 2px) * 2\n );\n }\n}\n\n.isActive {\n background: var(--j2-color-primary) !important;\n\n :global(.ant-select-selection-item-content) {\n color: white !important;\n }\n\n :global(.ant-select-suffix) {\n color: white !important;\n }\n}\n\n.menuContainer :global(.ant-select-item-option-selected) {\n background: var(--j2-color-primary) !important;\n}\n\n.menuContainer\n :global(.ant-select-item-option-selected)\n :global(.ant-select-item-option-content) {\n color: white;\n}\n\n.menuContainerMultiple :global(.ant-select-item-option-selected) {\n background: var(--j2-color-primary-bg-hover) !important;\n}\n\n.menuContainerMultiple\n :global(.ant-select-item-option-selected)\n :global(.ant-select-item-option-content) {\n color: inherit;\n}\n\n/*\n * Headlined variant styles\n * The select root owns its border and background in Ant Design 6.\n */\n\n.headlinedSelect:global(.ant-select):global(.ant-select-single) {\n font-size: var(--j2-font-size-heading-2);\n height: 40px;\n width: fit-content !important;\n}\n\n.headlinedSelect:global(.ant-select) {\n background: transparent;\n padding-left: 0;\n padding-right: 4px;\n font-size: var(--j2-font-size-heading-2);\n border-bottom: 1px solid transparent;\n border-radius: 0;\n}\n\n.headlinedSelect:global(.ant-select) :global(.ant-select-suffix) {\n height: 16px;\n width: 16px;\n right: 0;\n}\n\n.headlinedSelect:global(.ant-select) :global(.ant-select-content) {\n font-weight: 600;\n line-height: 1.3;\n}\n\n/* antd 6 outlines a focused borderless select through\n `:has(input:focus-visible)`, which a text input matches on a mouse click\n too, so every click boxed the headline. The underline below already marks\n focus. `!important` because antd's status variants of that rule reach\n (0,5,1) specificity. */\n.headlinedSelect:global(.ant-select) {\n outline: none !important;\n}\n\n/* Hover state - show underline */\n.headlinedSelect:global(.ant-select):hover {\n border-bottom-color: var(--j2-color-primary);\n}\n\n/* Open/focused state - keep underline and text color */\n.headlinedSelect:global(.ant-select-open),\n.headlinedSelect:global(.ant-select-focused) {\n border-bottom-color: var(--j2-color-primary);\n}\n\n.headlinedSelect:global(.ant-select-open) :global(.ant-select-content),\n.headlinedSelect:global(.ant-select-focused) :global(.ant-select-content) {\n color: inherit;\n}\n\n/* Headline dropdown styles - needs !important to override .menuContainer */\n.menuContainer.headlinedMenuContainer\n :global(.ant-select-item-option-selected) {\n background: var(--j2-color-primary) !important;\n}\n\n.menuContainer.headlinedMenuContainer\n :global(.ant-select-item-option-selected)\n :global(.ant-select-item-option-content) {\n color: white;\n}\n\n.clearAllButton {\n color: var(--j2-color-primary);\n}\n\n.clearAllButton:hover {\n background-color: var(--j2-color-primary-bg-hover);\n}\n\n/*\n * Dropdown trigger (`trigger=\"dropdown\"`)\n * Reads as emphasized text with an affordance, not as a link: semibold\n * primary text, no underline, and a fade on hover instead of a color shift.\n * The semibold weight is a utility class added in the component, skipped when\n * the consumer passes its own `font-*` weight. No cascade layers here: this\n * file is compiled into dist/style.css, and Tailwind 3 refuses a stylesheet\n * that declares a components layer without its own Tailwind directives.\n * Color needs `.ant-typography` to beat antd's link color.\n */\n\n.dropdownTrigger:global(.ant-typography),\n.dropdownTrigger:global(.ant-typography):hover,\n.dropdownTrigger:global(.ant-typography):focus {\n color: var(--j2-color-primary);\n text-decoration: none;\n}\n\n.dropdownTrigger:global(.ant-typography):hover {\n opacity: 0.7;\n}\n\n.dropdownTrigger:global(.ant-typography-disabled),\n.dropdownTrigger:global(.ant-typography-disabled):hover {\n color: var(--j2-color-text-disabled);\n opacity: 1;\n}\n\n/*\n * Field variant (`variant=\"field\"`)\n * A form field: full width, the field's own text color, a muted caret.\n */\n.fieldSelect :global(.ant-select-suffix) {\n color: var(--j2-color-text-secondary);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"SummarizedSelect.module.css.cjs","names":[],"sources":["../../../../src/components/select/SummarizedSelect.module.css"],"sourcesContent":[".hemisphericSelect {\n border-radius: 9999px !important;\n\n :global(.ant-select-placeholder) {\n color: var(--j2-color-primary) !important;\n }\n}\n\n.summarizedSelect {\n :global(.ant-select-suffix) {\n color: var(--j2-color-primary);\n }\n\n :global(.ant-select-selection-item) {\n background: none !important;\n border: none !important;\n padding-inline-end: 0 !important;\n margin-inline-end: 0 !important;\n }\n\n :global(.ant-select-selection-item-content) {\n margin-inline-end: 0 !important;\n }\n\n :global(.ant-select-content-item-rest) {\n max-width: 100%;\n }\n\n :global(.ant-select-content-item-suffix) {\n position: absolute;\n width: 1px;\n }\n\n /* antd 6 sizes a multiple select from its in-flow items. With the suffix\n (search input) and the placeholder both absolute, an empty select\n collapses to the font size (18px tall). Hold the row at one item's\n height, which the search input supplied before it was taken out of flow. */\n &:global(.ant-select-multiple) :global(.ant-select-content) {\n min-height: calc(\n var(--ant-select-multi-item-height, 24px) +\n var(--ant-select-internal_fixed_item_margin, 2px) * 2\n );\n }\n}\n\n.isActive {\n background: var(--j2-color-primary) !important;\n\n :global(.ant-select-selection-item-content) {\n color: white !important;\n }\n\n :global(.ant-select-suffix) {\n color: white !important;\n }\n}\n\n.menuContainer :global(.ant-select-item-option-selected) {\n background: var(--j2-color-primary) !important;\n}\n\n.menuContainer\n :global(.ant-select-item-option-selected)\n :global(.ant-select-item-option-content) {\n color: white;\n}\n\n.menuContainerMultiple :global(.ant-select-item-option-selected) {\n background: var(--j2-color-primary-bg-hover) !important;\n}\n\n.menuContainerMultiple\n :global(.ant-select-item-option-selected)\n :global(.ant-select-item-option-content) {\n color: inherit;\n}\n\n/*\n * Headlined variant styles\n * The select root owns its border and background in Ant Design 6.\n */\n\n.headlinedSelect:global(.ant-select):global(.ant-select-single) {\n font-size: var(--j2-font-size-heading-2);\n height: 40px;\n width: fit-content !important;\n}\n\n.headlinedSelect:global(.ant-select) {\n background: transparent;\n padding-left: 0;\n padding-right: 4px;\n font-size: var(--j2-font-size-heading-2);\n border-bottom: 1px solid transparent;\n border-radius: 0;\n}\n\n.headlinedSelect:global(.ant-select) :global(.ant-select-suffix) {\n height: 16px;\n width: 16px;\n right: 0;\n}\n\n.headlinedSelect:global(.ant-select) :global(.ant-select-content) {\n font-weight: 600;\n line-height: 1.3;\n}\n\n/* antd 6 outlines a focused borderless select through\n `:has(input:focus-visible)`, which a text input matches on a mouse click\n too, so every click boxed the headline. The underline below already marks\n focus. `!important` because antd's status variants of that rule reach\n (0,5,1) specificity. */\n.headlinedSelect:global(.ant-select) {\n outline: none !important;\n}\n\n/* Hover state - show underline */\n.headlinedSelect:global(.ant-select):hover {\n border-bottom-color: var(--j2-color-primary);\n}\n\n/* Open/focused state - keep underline and text color */\n.headlinedSelect:global(.ant-select-open),\n.headlinedSelect:global(.ant-select-focused) {\n border-bottom-color: var(--j2-color-primary);\n}\n\n.headlinedSelect:global(.ant-select-open) :global(.ant-select-content),\n.headlinedSelect:global(.ant-select-focused) :global(.ant-select-content) {\n color: inherit;\n}\n\n/* Headline dropdown styles - needs !important to override .menuContainer */\n.menuContainer.headlinedMenuContainer\n :global(.ant-select-item-option-selected) {\n background: var(--j2-color-primary) !important;\n}\n\n.menuContainer.headlinedMenuContainer\n :global(.ant-select-item-option-selected)\n :global(.ant-select-item-option-content) {\n color: white;\n}\n\n.clearAllButton {\n color: var(--j2-color-primary);\n}\n\n.clearAllButton:hover {\n background-color: var(--j2-color-primary-bg-hover);\n}\n\n/*\n * Dropdown trigger (`trigger=\"dropdown\"`)\n * Reads as emphasized text with an affordance, not as a link: semibold\n * primary text, no underline, and a fade on hover instead of a color shift.\n * The semibold weight is a utility class added in the component, skipped when\n * the consumer passes its own `font-*` weight. No cascade layers here: this\n * file is compiled into dist/style.css, and Tailwind 3 refuses a stylesheet\n * that declares a components layer without its own Tailwind directives.\n * Color needs `.ant-typography` to beat antd's link color.\n */\n\n.dropdownTrigger:global(.ant-typography),\n.dropdownTrigger:global(.ant-typography):hover,\n.dropdownTrigger:global(.ant-typography):focus {\n color: var(--j2-color-primary);\n text-decoration: none;\n}\n\n.dropdownTrigger:global(.ant-typography):hover {\n opacity: 0.7;\n}\n\n.dropdownTrigger:global(.ant-typography-disabled),\n.dropdownTrigger:global(.ant-typography-disabled):hover {\n color: var(--j2-color-text-disabled);\n opacity: 1;\n}\n\n/*\n * Field variant (`variant=\"field\"`)\n * A form field: full width, the field's own text color, a muted caret.\n */\n.fieldSelect :global(.ant-select-suffix) {\n color: var(--j2-color-text-secondary);\n}\n\n/* A line between option groups, drawn on every group after the first. */\n.groupDivider {\n border-top: 1px solid var(--j2-color-border-secondary);\n border-radius: 0 !important;\n}\n"],"mappings":""}
@@ -1,14 +1,15 @@
1
1
  //#region src/components/select/SummarizedSelect.module.css
2
- var hemisphericSelect = "_hemisphericSelect_3wupe_1";
3
- var summarizedSelect = "_summarizedSelect_3wupe_9";
4
- var isActive = "_isActive_3wupe_46";
5
- var menuContainer = "_menuContainer_3wupe_58";
6
- var menuContainerMultiple = "_menuContainerMultiple_3wupe_68";
7
- var headlinedSelect = "_headlinedSelect_3wupe_83";
8
- var headlinedMenuContainer = "_headlinedMenuContainer_3wupe_135";
9
- var clearAllButton = "_clearAllButton_3wupe_146";
10
- var dropdownTrigger = "_dropdownTrigger_3wupe_165";
11
- var fieldSelect = "_fieldSelect_3wupe_186";
2
+ var hemisphericSelect = "_hemisphericSelect_1pxzv_1";
3
+ var summarizedSelect = "_summarizedSelect_1pxzv_9";
4
+ var isActive = "_isActive_1pxzv_46";
5
+ var menuContainer = "_menuContainer_1pxzv_58";
6
+ var menuContainerMultiple = "_menuContainerMultiple_1pxzv_68";
7
+ var headlinedSelect = "_headlinedSelect_1pxzv_83";
8
+ var headlinedMenuContainer = "_headlinedMenuContainer_1pxzv_135";
9
+ var clearAllButton = "_clearAllButton_1pxzv_146";
10
+ var dropdownTrigger = "_dropdownTrigger_1pxzv_165";
11
+ var fieldSelect = "_fieldSelect_1pxzv_186";
12
+ var groupDivider = "_groupDivider_1pxzv_191";
12
13
  var SummarizedSelect_module_default = {
13
14
  hemisphericSelect,
14
15
  summarizedSelect,
@@ -19,9 +20,10 @@ var SummarizedSelect_module_default = {
19
20
  headlinedMenuContainer,
20
21
  clearAllButton,
21
22
  dropdownTrigger,
22
- fieldSelect
23
+ fieldSelect,
24
+ groupDivider
23
25
  };
24
26
  //#endregion
25
- export { clearAllButton, SummarizedSelect_module_default as default, dropdownTrigger, fieldSelect, headlinedMenuContainer, headlinedSelect, hemisphericSelect, isActive, menuContainer, menuContainerMultiple, summarizedSelect };
27
+ export { clearAllButton, SummarizedSelect_module_default as default, dropdownTrigger, fieldSelect, groupDivider, headlinedMenuContainer, headlinedSelect, hemisphericSelect, isActive, menuContainer, menuContainerMultiple, summarizedSelect };
26
28
 
27
29
  //# sourceMappingURL=SummarizedSelect.module.css.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SummarizedSelect.module.css.js","names":[],"sources":["../../../../src/components/select/SummarizedSelect.module.css"],"sourcesContent":[".hemisphericSelect {\n border-radius: 9999px !important;\n\n :global(.ant-select-placeholder) {\n color: var(--j2-color-primary) !important;\n }\n}\n\n.summarizedSelect {\n :global(.ant-select-suffix) {\n color: var(--j2-color-primary);\n }\n\n :global(.ant-select-selection-item) {\n background: none !important;\n border: none !important;\n padding-inline-end: 0 !important;\n margin-inline-end: 0 !important;\n }\n\n :global(.ant-select-selection-item-content) {\n margin-inline-end: 0 !important;\n }\n\n :global(.ant-select-content-item-rest) {\n max-width: 100%;\n }\n\n :global(.ant-select-content-item-suffix) {\n position: absolute;\n width: 1px;\n }\n\n /* antd 6 sizes a multiple select from its in-flow items. With the suffix\n (search input) and the placeholder both absolute, an empty select\n collapses to the font size (18px tall). Hold the row at one item's\n height, which the search input supplied before it was taken out of flow. */\n &:global(.ant-select-multiple) :global(.ant-select-content) {\n min-height: calc(\n var(--ant-select-multi-item-height, 24px) +\n var(--ant-select-internal_fixed_item_margin, 2px) * 2\n );\n }\n}\n\n.isActive {\n background: var(--j2-color-primary) !important;\n\n :global(.ant-select-selection-item-content) {\n color: white !important;\n }\n\n :global(.ant-select-suffix) {\n color: white !important;\n }\n}\n\n.menuContainer :global(.ant-select-item-option-selected) {\n background: var(--j2-color-primary) !important;\n}\n\n.menuContainer\n :global(.ant-select-item-option-selected)\n :global(.ant-select-item-option-content) {\n color: white;\n}\n\n.menuContainerMultiple :global(.ant-select-item-option-selected) {\n background: var(--j2-color-primary-bg-hover) !important;\n}\n\n.menuContainerMultiple\n :global(.ant-select-item-option-selected)\n :global(.ant-select-item-option-content) {\n color: inherit;\n}\n\n/*\n * Headlined variant styles\n * The select root owns its border and background in Ant Design 6.\n */\n\n.headlinedSelect:global(.ant-select):global(.ant-select-single) {\n font-size: var(--j2-font-size-heading-2);\n height: 40px;\n width: fit-content !important;\n}\n\n.headlinedSelect:global(.ant-select) {\n background: transparent;\n padding-left: 0;\n padding-right: 4px;\n font-size: var(--j2-font-size-heading-2);\n border-bottom: 1px solid transparent;\n border-radius: 0;\n}\n\n.headlinedSelect:global(.ant-select) :global(.ant-select-suffix) {\n height: 16px;\n width: 16px;\n right: 0;\n}\n\n.headlinedSelect:global(.ant-select) :global(.ant-select-content) {\n font-weight: 600;\n line-height: 1.3;\n}\n\n/* antd 6 outlines a focused borderless select through\n `:has(input:focus-visible)`, which a text input matches on a mouse click\n too, so every click boxed the headline. The underline below already marks\n focus. `!important` because antd's status variants of that rule reach\n (0,5,1) specificity. */\n.headlinedSelect:global(.ant-select) {\n outline: none !important;\n}\n\n/* Hover state - show underline */\n.headlinedSelect:global(.ant-select):hover {\n border-bottom-color: var(--j2-color-primary);\n}\n\n/* Open/focused state - keep underline and text color */\n.headlinedSelect:global(.ant-select-open),\n.headlinedSelect:global(.ant-select-focused) {\n border-bottom-color: var(--j2-color-primary);\n}\n\n.headlinedSelect:global(.ant-select-open) :global(.ant-select-content),\n.headlinedSelect:global(.ant-select-focused) :global(.ant-select-content) {\n color: inherit;\n}\n\n/* Headline dropdown styles - needs !important to override .menuContainer */\n.menuContainer.headlinedMenuContainer\n :global(.ant-select-item-option-selected) {\n background: var(--j2-color-primary) !important;\n}\n\n.menuContainer.headlinedMenuContainer\n :global(.ant-select-item-option-selected)\n :global(.ant-select-item-option-content) {\n color: white;\n}\n\n.clearAllButton {\n color: var(--j2-color-primary);\n}\n\n.clearAllButton:hover {\n background-color: var(--j2-color-primary-bg-hover);\n}\n\n/*\n * Dropdown trigger (`trigger=\"dropdown\"`)\n * Reads as emphasized text with an affordance, not as a link: semibold\n * primary text, no underline, and a fade on hover instead of a color shift.\n * The semibold weight is a utility class added in the component, skipped when\n * the consumer passes its own `font-*` weight. No cascade layers here: this\n * file is compiled into dist/style.css, and Tailwind 3 refuses a stylesheet\n * that declares a components layer without its own Tailwind directives.\n * Color needs `.ant-typography` to beat antd's link color.\n */\n\n.dropdownTrigger:global(.ant-typography),\n.dropdownTrigger:global(.ant-typography):hover,\n.dropdownTrigger:global(.ant-typography):focus {\n color: var(--j2-color-primary);\n text-decoration: none;\n}\n\n.dropdownTrigger:global(.ant-typography):hover {\n opacity: 0.7;\n}\n\n.dropdownTrigger:global(.ant-typography-disabled),\n.dropdownTrigger:global(.ant-typography-disabled):hover {\n color: var(--j2-color-text-disabled);\n opacity: 1;\n}\n\n/*\n * Field variant (`variant=\"field\"`)\n * A form field: full width, the field's own text color, a muted caret.\n */\n.fieldSelect :global(.ant-select-suffix) {\n color: var(--j2-color-text-secondary);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"SummarizedSelect.module.css.js","names":[],"sources":["../../../../src/components/select/SummarizedSelect.module.css"],"sourcesContent":[".hemisphericSelect {\n border-radius: 9999px !important;\n\n :global(.ant-select-placeholder) {\n color: var(--j2-color-primary) !important;\n }\n}\n\n.summarizedSelect {\n :global(.ant-select-suffix) {\n color: var(--j2-color-primary);\n }\n\n :global(.ant-select-selection-item) {\n background: none !important;\n border: none !important;\n padding-inline-end: 0 !important;\n margin-inline-end: 0 !important;\n }\n\n :global(.ant-select-selection-item-content) {\n margin-inline-end: 0 !important;\n }\n\n :global(.ant-select-content-item-rest) {\n max-width: 100%;\n }\n\n :global(.ant-select-content-item-suffix) {\n position: absolute;\n width: 1px;\n }\n\n /* antd 6 sizes a multiple select from its in-flow items. With the suffix\n (search input) and the placeholder both absolute, an empty select\n collapses to the font size (18px tall). Hold the row at one item's\n height, which the search input supplied before it was taken out of flow. */\n &:global(.ant-select-multiple) :global(.ant-select-content) {\n min-height: calc(\n var(--ant-select-multi-item-height, 24px) +\n var(--ant-select-internal_fixed_item_margin, 2px) * 2\n );\n }\n}\n\n.isActive {\n background: var(--j2-color-primary) !important;\n\n :global(.ant-select-selection-item-content) {\n color: white !important;\n }\n\n :global(.ant-select-suffix) {\n color: white !important;\n }\n}\n\n.menuContainer :global(.ant-select-item-option-selected) {\n background: var(--j2-color-primary) !important;\n}\n\n.menuContainer\n :global(.ant-select-item-option-selected)\n :global(.ant-select-item-option-content) {\n color: white;\n}\n\n.menuContainerMultiple :global(.ant-select-item-option-selected) {\n background: var(--j2-color-primary-bg-hover) !important;\n}\n\n.menuContainerMultiple\n :global(.ant-select-item-option-selected)\n :global(.ant-select-item-option-content) {\n color: inherit;\n}\n\n/*\n * Headlined variant styles\n * The select root owns its border and background in Ant Design 6.\n */\n\n.headlinedSelect:global(.ant-select):global(.ant-select-single) {\n font-size: var(--j2-font-size-heading-2);\n height: 40px;\n width: fit-content !important;\n}\n\n.headlinedSelect:global(.ant-select) {\n background: transparent;\n padding-left: 0;\n padding-right: 4px;\n font-size: var(--j2-font-size-heading-2);\n border-bottom: 1px solid transparent;\n border-radius: 0;\n}\n\n.headlinedSelect:global(.ant-select) :global(.ant-select-suffix) {\n height: 16px;\n width: 16px;\n right: 0;\n}\n\n.headlinedSelect:global(.ant-select) :global(.ant-select-content) {\n font-weight: 600;\n line-height: 1.3;\n}\n\n/* antd 6 outlines a focused borderless select through\n `:has(input:focus-visible)`, which a text input matches on a mouse click\n too, so every click boxed the headline. The underline below already marks\n focus. `!important` because antd's status variants of that rule reach\n (0,5,1) specificity. */\n.headlinedSelect:global(.ant-select) {\n outline: none !important;\n}\n\n/* Hover state - show underline */\n.headlinedSelect:global(.ant-select):hover {\n border-bottom-color: var(--j2-color-primary);\n}\n\n/* Open/focused state - keep underline and text color */\n.headlinedSelect:global(.ant-select-open),\n.headlinedSelect:global(.ant-select-focused) {\n border-bottom-color: var(--j2-color-primary);\n}\n\n.headlinedSelect:global(.ant-select-open) :global(.ant-select-content),\n.headlinedSelect:global(.ant-select-focused) :global(.ant-select-content) {\n color: inherit;\n}\n\n/* Headline dropdown styles - needs !important to override .menuContainer */\n.menuContainer.headlinedMenuContainer\n :global(.ant-select-item-option-selected) {\n background: var(--j2-color-primary) !important;\n}\n\n.menuContainer.headlinedMenuContainer\n :global(.ant-select-item-option-selected)\n :global(.ant-select-item-option-content) {\n color: white;\n}\n\n.clearAllButton {\n color: var(--j2-color-primary);\n}\n\n.clearAllButton:hover {\n background-color: var(--j2-color-primary-bg-hover);\n}\n\n/*\n * Dropdown trigger (`trigger=\"dropdown\"`)\n * Reads as emphasized text with an affordance, not as a link: semibold\n * primary text, no underline, and a fade on hover instead of a color shift.\n * The semibold weight is a utility class added in the component, skipped when\n * the consumer passes its own `font-*` weight. No cascade layers here: this\n * file is compiled into dist/style.css, and Tailwind 3 refuses a stylesheet\n * that declares a components layer without its own Tailwind directives.\n * Color needs `.ant-typography` to beat antd's link color.\n */\n\n.dropdownTrigger:global(.ant-typography),\n.dropdownTrigger:global(.ant-typography):hover,\n.dropdownTrigger:global(.ant-typography):focus {\n color: var(--j2-color-primary);\n text-decoration: none;\n}\n\n.dropdownTrigger:global(.ant-typography):hover {\n opacity: 0.7;\n}\n\n.dropdownTrigger:global(.ant-typography-disabled),\n.dropdownTrigger:global(.ant-typography-disabled):hover {\n color: var(--j2-color-text-disabled);\n opacity: 1;\n}\n\n/*\n * Field variant (`variant=\"field\"`)\n * A form field: full width, the field's own text color, a muted caret.\n */\n.fieldSelect :global(.ant-select-suffix) {\n color: var(--j2-color-text-secondary);\n}\n\n/* A line between option groups, drawn on every group after the first. */\n.groupDivider {\n border-top: 1px solid var(--j2-color-border-secondary);\n border-radius: 0 !important;\n}\n"],"mappings":""}
@@ -0,0 +1,22 @@
1
+ const require_runtime = require("../../../_virtual/_rolldown/runtime.cjs");
2
+ let antd = require("antd");
3
+ let react_jsx_runtime = require("react/jsx-runtime");
4
+ let classnames = require("classnames");
5
+ classnames = require_runtime.__toESM(classnames, 1);
6
+ //#region src/components/slider/Slider.tsx
7
+ /**
8
+ * antd's Slider with the J2 track and handle (theme tokens in `appTheme`) and
9
+ * the DS tooltip convention: no arrow, unless the consumer asks for one.
10
+ */
11
+ var Slider = ({ className, tooltip, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(antd.Slider, {
12
+ ...props,
13
+ className: (0, classnames.default)("j2-slider", className),
14
+ tooltip: {
15
+ arrow: false,
16
+ ...tooltip
17
+ }
18
+ });
19
+ //#endregion
20
+ exports.Slider = Slider;
21
+
22
+ //# sourceMappingURL=Slider.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Slider.cjs","names":["AntSlider","cx"],"sources":["../../../../src/components/slider/Slider.tsx"],"sourcesContent":["import { Slider as AntSlider } from 'antd'\nimport type { SliderRangeProps, SliderSingleProps } from 'antd/es/slider'\nimport cx from 'classnames'\n\nexport type Props = SliderSingleProps | SliderRangeProps\n\n/**\n * antd's Slider with the J2 track and handle (theme tokens in `appTheme`) and\n * the DS tooltip convention: no arrow, unless the consumer asks for one.\n */\nexport const Slider = ({ className, tooltip, ...props }: Props) => (\n <AntSlider\n {...(props as SliderSingleProps)}\n className={cx('j2-slider', className)}\n tooltip={{ arrow: false, ...tooltip }}\n />\n)\n"],"mappings":";;;;;;;;;;AAUA,IAAa,UAAU,EAAE,WAAW,SAAS,GAAG,YAC9C,iBAAA,GAAA,kBAAA,IAAA,CAACA,KAAAA,QAAD;CACE,GAAK;CACL,YAAA,GAAWC,WAAAA,QAAAA,CAAG,aAAa,SAAS;CACpC,SAAS;EAAE,OAAO;EAAO,GAAG;CAAQ;AACrC,CAAA"}
@@ -0,0 +1,7 @@
1
+ import { SliderRangeProps, SliderSingleProps } from 'antd/es/slider';
2
+ export type Props = SliderSingleProps | SliderRangeProps;
3
+ /**
4
+ * antd's Slider with the J2 track and handle (theme tokens in `appTheme`) and
5
+ * the DS tooltip convention: no arrow, unless the consumer asks for one.
6
+ */
7
+ export declare const Slider: ({ className, tooltip, ...props }: Props) => import('react').JSX.Element;
@@ -0,0 +1,20 @@
1
+ import { Slider } from "antd";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import cx from "classnames";
4
+ //#region src/components/slider/Slider.tsx
5
+ /**
6
+ * antd's Slider with the J2 track and handle (theme tokens in `appTheme`) and
7
+ * the DS tooltip convention: no arrow, unless the consumer asks for one.
8
+ */
9
+ var Slider$1 = ({ className, tooltip, ...props }) => /* @__PURE__ */ jsx(Slider, {
10
+ ...props,
11
+ className: cx("j2-slider", className),
12
+ tooltip: {
13
+ arrow: false,
14
+ ...tooltip
15
+ }
16
+ });
17
+ //#endregion
18
+ export { Slider$1 as Slider };
19
+
20
+ //# sourceMappingURL=Slider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Slider.js","names":["Slider","AntSlider"],"sources":["../../../../src/components/slider/Slider.tsx"],"sourcesContent":["import { Slider as AntSlider } from 'antd'\nimport type { SliderRangeProps, SliderSingleProps } from 'antd/es/slider'\nimport cx from 'classnames'\n\nexport type Props = SliderSingleProps | SliderRangeProps\n\n/**\n * antd's Slider with the J2 track and handle (theme tokens in `appTheme`) and\n * the DS tooltip convention: no arrow, unless the consumer asks for one.\n */\nexport const Slider = ({ className, tooltip, ...props }: Props) => (\n <AntSlider\n {...(props as SliderSingleProps)}\n className={cx('j2-slider', className)}\n tooltip={{ arrow: false, ...tooltip }}\n />\n)\n"],"mappings":";;;;;;;;AAUA,IAAaA,YAAU,EAAE,WAAW,SAAS,GAAG,YAC9C,oBAACC,QAAD;CACE,GAAK;CACL,WAAW,GAAG,aAAa,SAAS;CACpC,SAAS;EAAE,OAAO;EAAO,GAAG;CAAQ;AACrC,CAAA"}
@@ -0,0 +1 @@
1
+ export { Slider } from './Slider.js';