coles-solid-library 0.4.4 → 0.4.6

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/index.esm.js CHANGED
@@ -516,7 +516,7 @@ function styleInject(css, ref) {
516
516
  }
517
517
  }
518
518
 
519
- var css_248z$j = ".Button-module_customButtonStyle__RCNcn {\n border-radius: 8px;\n font-family: \"Roboto, sans-serif\";\n padding: 8px 8px;\n border: none;\n outline: none;\n transition: transform 0.2s ease, background 0.2s ease;\n}\n.Button-module_customButtonStyle__RCNcn:active {\n transform: scale(0.9);\n box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.3);\n}\n.Button-module_customButtonStyle__RCNcn:not(:disabled):hover {\n cursor: pointer;\n box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.15);\n}\n.Button-module_customButtonStyle__RCNcn:disabled:hover {\n cursor: not-allowed;\n}\n\n.Button-module_primary__st6yY {\n background-color: var(--primary-color, #4CAF50);\n color: var(--on-primary-color, #fff);\n}\n\n.Button-module_primaryVariant__ObiQc {\n background-color: var(--primary-color-varient, #43A047);\n color: var(--on-primary-color, #fff);\n}\n\n.Button-module_secondary__j-3rj {\n background-color: var(--secondary-color, #14b9c3);\n color: var(--on-secondary-color, #000000);\n}\n\n.Button-module_secondaryVariant__xFdCV {\n background-color: var(--secondary-color-varient, #0b969f);\n color: var(--on-secondary-color, #000000);\n}\n\n.Button-module_background__ebjke {\n background-color: var(--background-color, #ffffff);\n color: var(--on-background-color, #000000);\n}\n\n.Button-module_surface__wzdJD {\n background-color: var(--surface-color, #EEEEEE);\n color: var(--on-surface-color, #000000);\n}\n\n.Button-module_surfaceVariant__SkL3X {\n background-color: var(--surface-color-variant, #ccc);\n color: var(--on-surface-color, #000000);\n}\n\n.Button-module_container__0j8md {\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n}\n\n.Button-module_error__1zBsf {\n background-color: var(--error-color, #B00020);\n color: var(--on-error-color, #ffffff);\n}\n\n.Button-module_borderPrimary__k5fYt {\n border: 1px solid var(--primary-color, #4CAF50);\n}\n\n.Button-module_borderPrimaryVariant__-uFUm {\n border: 1px solid var(--primary-color-varient, #43A047);\n}\n\n.Button-module_borderSecondary__hzoGk {\n border: 1px solid var(--secondary-color, #14b9c3);\n}\n\n.Button-module_borderSecondaryVariant__-75Li {\n border: 1px solid var(--secondary-color-varient, #0b969f);\n}\n\n.Button-module_borderBackground__Uyf-G {\n border: 1px solid var(--background-color, #ffffff);\n}\n\n.Button-module_borderSurface__q9bRE {\n border: 1px solid var(--surface-color, #EEEEEE);\n}\n\n.Button-module_borderSurfaceVariant__ZHVd0 {\n border: 1px solid var(--surface-color-variant, #ccc);\n}\n\n.Button-module_borderContainer__mXwj- {\n border: 1px solid var(--container-color, #ffffff);\n}\n\n.Button-module_borderError__IChtd {\n border: 1px solid var(--error-color, #B00020);\n}\n\n.Button-module_none__YrUD1 {\n border: none;\n}\n\n.Button-module_transparent__6v0QA {\n background-color: transparent !important;\n border: none;\n outline: none;\n padding: 0px;\n margin: 0px;\n}";
519
+ var css_248z$j = ".Button-module_customButtonStyle__RCNcn {\n border-radius: 8px;\n font-family: \"Roboto, sans-serif\";\n padding: 8px 8px;\n border: none;\n outline: none;\n transition: transform 0.2s ease, background 0.2s ease;\n}\n.Button-module_customButtonStyle__RCNcn:active {\n transform: scale(0.9);\n box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.3);\n}\n.Button-module_customButtonStyle__RCNcn:not(:disabled):hover {\n cursor: pointer;\n box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.15);\n}\n.Button-module_customButtonStyle__RCNcn:disabled {\n opacity: 0.6;\n}\n.Button-module_customButtonStyle__RCNcn:disabled:hover {\n cursor: not-allowed;\n}\n\n.Button-module_primary__st6yY {\n background-color: var(--primary-color, #4CAF50);\n color: var(--on-primary-color, #fff);\n}\n\n.Button-module_primaryVariant__ObiQc {\n background-color: var(--primary-color-varient, #43A047);\n color: var(--on-primary-color, #fff);\n}\n\n.Button-module_secondary__j-3rj {\n background-color: var(--secondary-color, #14b9c3);\n color: var(--on-secondary-color, #000000);\n}\n\n.Button-module_secondaryVariant__xFdCV {\n background-color: var(--secondary-color-varient, #0b969f);\n color: var(--on-secondary-color, #000000);\n}\n\n.Button-module_background__ebjke {\n background-color: var(--background-color, #ffffff);\n color: var(--on-background-color, #000000);\n}\n\n.Button-module_surface__wzdJD {\n background-color: var(--surface-color, #EEEEEE);\n color: var(--on-surface-color, #000000);\n}\n\n.Button-module_surfaceVariant__SkL3X {\n background-color: var(--surface-color-variant, #ccc);\n color: var(--on-surface-color, #000000);\n}\n\n.Button-module_container__0j8md {\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n}\n\n.Button-module_error__1zBsf {\n background-color: var(--error-color, #B00020);\n color: var(--on-error-color, #ffffff);\n}\n\n.Button-module_borderPrimary__k5fYt {\n border: 1px solid var(--primary-color, #4CAF50);\n}\n\n.Button-module_borderPrimaryVariant__-uFUm {\n border: 1px solid var(--primary-color-varient, #43A047);\n}\n\n.Button-module_borderSecondary__hzoGk {\n border: 1px solid var(--secondary-color, #14b9c3);\n}\n\n.Button-module_borderSecondaryVariant__-75Li {\n border: 1px solid var(--secondary-color-varient, #0b969f);\n}\n\n.Button-module_borderBackground__Uyf-G {\n border: 1px solid var(--background-color, #ffffff);\n}\n\n.Button-module_borderSurface__q9bRE {\n border: 1px solid var(--surface-color, #EEEEEE);\n}\n\n.Button-module_borderSurfaceVariant__ZHVd0 {\n border: 1px solid var(--surface-color-variant, #ccc);\n}\n\n.Button-module_borderContainer__mXwj- {\n border: 1px solid var(--container-color, #ffffff);\n}\n\n.Button-module_borderError__IChtd {\n border: 1px solid var(--error-color, #B00020);\n}\n\n.Button-module_none__YrUD1 {\n border: none;\n}\n\n.Button-module_transparent__6v0QA {\n background-color: transparent !important;\n border: none;\n outline: none;\n padding: 0px;\n margin: 0px;\n}";
520
520
  var style$8 = {"customButtonStyle":"Button-module_customButtonStyle__RCNcn","primary":"Button-module_primary__st6yY","primaryVariant":"Button-module_primaryVariant__ObiQc","secondary":"Button-module_secondary__j-3rj","secondaryVariant":"Button-module_secondaryVariant__xFdCV","background":"Button-module_background__ebjke","surface":"Button-module_surface__wzdJD","surfaceVariant":"Button-module_surfaceVariant__SkL3X","container":"Button-module_container__0j8md","error":"Button-module_error__1zBsf","borderPrimary":"Button-module_borderPrimary__k5fYt","borderPrimaryVariant":"Button-module_borderPrimaryVariant__-uFUm","borderSecondary":"Button-module_borderSecondary__hzoGk","borderSecondaryVariant":"Button-module_borderSecondaryVariant__-75Li","borderBackground":"Button-module_borderBackground__Uyf-G","borderSurface":"Button-module_borderSurface__q9bRE","borderSurfaceVariant":"Button-module_borderSurfaceVariant__ZHVd0","borderContainer":"Button-module_borderContainer__mXwj-","borderError":"Button-module_borderError__IChtd","none":"Button-module_none__YrUD1","transparent":"Button-module_transparent__6v0QA"};
521
521
  styleInject(css_248z$j);
522
522
 
@@ -578,8 +578,8 @@ styleInject(css_248z$i);
578
578
 
579
579
  var _tmpl$$n = /*#__PURE__*/template(`<div>No <!> Found`),
580
580
  _tmpl$2$c = /*#__PURE__*/template(`<div>No Elements Found`),
581
- _tmpl$3$4 = /*#__PURE__*/template(`<div>`),
582
- _tmpl$4$2 = /*#__PURE__*/template(`<div><div><div></div></div><div>`);
581
+ _tmpl$3$5 = /*#__PURE__*/template(`<div>`),
582
+ _tmpl$4$3 = /*#__PURE__*/template(`<div><div><div></div></div><div>`);
583
583
  const carouselTitleContext = createContext(createSignal([]));
584
584
  const Provider$2 = props => {
585
585
  return createComponent(carouselTitleContext.Provider, {
@@ -684,7 +684,7 @@ const Carousel = ({
684
684
  return createSignal([]);
685
685
  },
686
686
  get children() {
687
- var _el$6 = _tmpl$4$2(),
687
+ var _el$6 = _tmpl$4$3(),
688
688
  _el$7 = _el$6.firstChild,
689
689
  _el$8 = _el$7.firstChild,
690
690
  _el$11 = _el$7.nextSibling;
@@ -701,7 +701,7 @@ const Carousel = ({
701
701
  return Object.keys(props).includes('elements');
702
702
  },
703
703
  get children() {
704
- var _el$9 = _tmpl$3$4();
704
+ var _el$9 = _tmpl$3$5();
705
705
  insert(_el$9, slideName);
706
706
  createRenderEffect(() => className(_el$9, `${style$7.carouselSlide}`));
707
707
  return _el$9;
@@ -712,7 +712,7 @@ const Carousel = ({
712
712
  return Object.keys(props).includes('children');
713
713
  },
714
714
  get children() {
715
- var _el$10 = _tmpl$3$4();
715
+ var _el$10 = _tmpl$3$5();
716
716
  insert(_el$10, slideName);
717
717
  createRenderEffect(() => className(_el$10, `${style$7.carouselSlide}`));
718
718
  return _el$10;
@@ -761,11 +761,11 @@ styleInject(css_248z$h);
761
761
 
762
762
  var _tmpl$$m = /*#__PURE__*/template(`<span>`),
763
763
  _tmpl$2$b = /*#__PURE__*/template(`<span>:`),
764
- _tmpl$3$3 = /*#__PURE__*/template(`<span><span>`);
764
+ _tmpl$3$4 = /*#__PURE__*/template(`<span><span>`);
765
765
  const Chip = props => {
766
766
  const hoverChip = props.onClick ? `${style$6.hover}` : "";
767
767
  return (() => {
768
- var _el$ = _tmpl$3$3(),
768
+ var _el$ = _tmpl$3$4(),
769
769
  _el$4 = _el$.firstChild;
770
770
  addEventListener(_el$, "click", props.onClick, true);
771
771
  insert(_el$, createComponent(Show, {
@@ -1395,8 +1395,102 @@ function useClickOutside(elementRefs, callback) {
1395
1395
  });
1396
1396
  }
1397
1397
 
1398
+ /**
1399
+ * Shared hook for positioning overlay elements (dropdowns, menus, etc.)
1400
+ * relative to an anchor element. Handles viewport boundary detection,
1401
+ * above/below placement, scroll and resize tracking.
1402
+ *
1403
+ * @param anchorRef - Accessor returning the anchor DOM element
1404
+ * @param overlayRef - Accessor returning the overlay DOM element
1405
+ * @param open - Accessor returning whether the overlay is currently open
1406
+ * @param config - Optional positioning configuration
1407
+ */
1408
+ function useOverlayPosition(anchorRef, overlayRef, open, config) {
1409
+ const VIEWPORT_MARGIN = 4;
1410
+ const MIN_HEIGHT = 160;
1411
+ const [dropTop, setDropTop] = createSignal(false);
1412
+ const getOverlayMetrics = () => {
1413
+ const el = overlayRef();
1414
+ if (!el) return {
1415
+ height: 0,
1416
+ width: 0
1417
+ };
1418
+ const rect = el.getBoundingClientRect();
1419
+ // When scaled/hidden, height can be 0; fallback to scrollHeight
1420
+ const height = rect.height === 0 ? el.scrollHeight || rect.height : rect.height;
1421
+ return {
1422
+ height,
1423
+ width: rect.width
1424
+ };
1425
+ };
1426
+ const updatePosition = () => {
1427
+ const overlay = overlayRef();
1428
+ const anchor = anchorRef();
1429
+ if (!overlay || !anchor) return;
1430
+ const baseRect = anchor.getBoundingClientRect();
1431
+ const {
1432
+ height: overlayHeight
1433
+ } = getOverlayMetrics();
1434
+ const spaceBelow = window.innerHeight - baseRect.bottom;
1435
+ const spaceAbove = baseRect.top;
1436
+ // Decide orientation: prefer below if it fits, else above, else whichever has more room
1437
+ let placeAbove = false;
1438
+ if (overlayHeight + VIEWPORT_MARGIN <= spaceBelow) {
1439
+ placeAbove = false;
1440
+ } else if (overlayHeight + VIEWPORT_MARGIN <= spaceAbove) {
1441
+ placeAbove = true;
1442
+ } else {
1443
+ placeAbove = spaceAbove > spaceBelow;
1444
+ }
1445
+ setDropTop(placeAbove);
1446
+ // Clamp max-height to available space
1447
+ const availableSpace = (placeAbove ? spaceAbove : spaceBelow) - VIEWPORT_MARGIN;
1448
+ const maxHeight = Math.max(MIN_HEIGHT, availableSpace);
1449
+ let newY;
1450
+ if (!placeAbove) {
1451
+ newY = baseRect.bottom + window.scrollY;
1452
+ if (newY + overlayHeight + VIEWPORT_MARGIN > window.scrollY + window.innerHeight) {
1453
+ newY = window.scrollY + window.innerHeight - overlayHeight - VIEWPORT_MARGIN;
1454
+ }
1455
+ } else {
1456
+ newY = baseRect.top + window.scrollY - overlayHeight;
1457
+ if (newY < window.scrollY + VIEWPORT_MARGIN) {
1458
+ newY = window.scrollY + VIEWPORT_MARGIN;
1459
+ }
1460
+ }
1461
+ // Final guard
1462
+ if (newY < window.scrollY + VIEWPORT_MARGIN) {
1463
+ newY = window.scrollY + VIEWPORT_MARGIN;
1464
+ }
1465
+ const newX = baseRect.left + window.scrollX;
1466
+ overlay.style.left = `${newX}px`;
1467
+ overlay.style.top = `${newY}px`;
1468
+ overlay.style.width = `${baseRect.width}px`;
1469
+ overlay.style.maxHeight = `${maxHeight}px`;
1470
+ };
1471
+ // Re-position when open changes
1472
+ createEffect(() => {
1473
+ if (open()) {
1474
+ queueMicrotask(() => updatePosition());
1475
+ }
1476
+ });
1477
+ // Attach scroll/resize listeners
1478
+ onMount(() => {
1479
+ document.addEventListener('scroll', updatePosition, true);
1480
+ window.addEventListener('resize', updatePosition);
1481
+ onCleanup(() => {
1482
+ document.removeEventListener('scroll', updatePosition, true);
1483
+ window.removeEventListener('resize', updatePosition);
1484
+ });
1485
+ });
1486
+ return {
1487
+ dropTop,
1488
+ updatePosition
1489
+ };
1490
+ }
1491
+
1398
1492
  var css_248z$e = "@charset \"UTF-8\";\n.input-module_input__-LMoi {\n width: 100%;\n max-width: 400px;\n border-radius: var(--border-radius-lg, 16px);\n font-size: var(--font-size-base, 16px);\n transition: border 0.7s ease, padding 0.7s ease;\n}\n@media screen and (max-width: 768px) {\n .input-module_input__-LMoi {\n width: 100%;\n max-width: 100%;\n }\n}\n.input-module_input__-LMoi[type=checkbox] {\n width: -moz-min-content;\n width: min-content;\n -webkit-appearance: none;\n border: 1px solid #cacece;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05), inset 0px -15px 10px -12px rgba(0, 0, 0, 0.05);\n padding: var(--spacing-1, 8px);\n border-radius: var(--border-radius-sm);\n display: inline-block;\n position: relative;\n}\n.input-module_input__-LMoi[type=checkbox]:checked {\n background-color: inherit;\n border: 1px solid #adb8c0;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05), inset 0px -15px 10px -12px rgba(0, 0, 0, 0.05), inset 15px 10px -12px rgba(255, 255, 255, 0.1);\n color: inherit;\n}\n.input-module_input__-LMoi[type=checkbox]:checked:after {\n content: \"✔\";\n position: absolute;\n top: -15%;\n left: 15%;\n width: 10px;\n height: 10px;\n border-radius: 10%;\n}\n.input-module_input__-LMoi:not([type=checkbox])::-moz-placeholder {\n opacity: 0;\n}\n.input-module_input__-LMoi:not([type=checkbox])::placeholder {\n opacity: 0;\n}\n.input-module_input__-LMoi:focus {\n outline: none;\n}\n.input-module_input__-LMoi.input-module_error__vs2kz {\n border: 1px solid var(--warn-color);\n}\n.input-module_input__-LMoi.input-module_success__beiu5 {\n border: 1px solid green;\n}\n.input-module_input__-LMoi.input-module_warning__b6S5s {\n border: 1px solid orange;\n}\n.input-module_input__-LMoi.input-module_info__pWO0n {\n border: 1px solid blue;\n}\n.input-module_input__-LMoi.input-module_disabled__40ZHw {\n border: 1px solid gray;\n}\n\n.input-module_inFormField__kk-PD {\n border: none;\n outline: none;\n transition: padding 0.7s ease;\n}\n\n.input-module_checkbox__Yu-9M {\n cursor: pointer;\n}\n\n.input-module_transparent__aXcGX {\n background-color: inherit !important;\n opacity: 1;\n color: inherit !important;\n border: none;\n}\n.input-module_transparent__aXcGX :focus {\n outline: none;\n}";
1399
- var styles$9 = {"input":"input-module_input__-LMoi","inFormField":"input-module_inFormField__kk-PD","transparent":"input-module_transparent__aXcGX"};
1493
+ var styles$9 = {"input":"input-module_input__-LMoi","disabled":"input-module_disabled__40ZHw","inFormField":"input-module_inFormField__kk-PD","transparent":"input-module_transparent__aXcGX"};
1400
1494
  styleInject(css_248z$e);
1401
1495
 
1402
1496
  var _tmpl$$j = /*#__PURE__*/template(`<form>`);
@@ -1583,17 +1677,13 @@ const Input = props => {
1583
1677
  return inputValue();
1584
1678
  },
1585
1679
  "onFocus": () => {
1680
+ if (props.disabled) return;
1586
1681
  if (!isNullish(context.getName)) {
1587
1682
  context.setFocused?.(true);
1588
- // Mark dirty on initial focus if part of a form (requested behavior)
1589
- const formName = context.formName;
1590
- if (formName && formContext?.formGroup?.markDirty) {
1591
- const meta = formContext.formGroup.getMeta(formName);
1592
- if (meta && !meta.dirty) formContext.formGroup.markDirty(formName);
1593
- }
1594
1683
  }
1595
1684
  },
1596
1685
  "onBlur": e => {
1686
+ if (props.disabled) return;
1597
1687
  if (!isNullish(context.getName)) {
1598
1688
  context?.setFocused?.(prev => {
1599
1689
  if (prev) {
@@ -1612,7 +1702,7 @@ const Input = props => {
1612
1702
  },
1613
1703
  "onChange": onChange,
1614
1704
  get ["class"]() {
1615
- return `${styles$9.input} ${customProps.transparent ? styles$9.transparent : ""} ${!!context?.getName?.() ? styles$9.inFormField : ""} ${props?.class ?? ""}`;
1705
+ return `${styles$9.input} ${props.disabled ? styles$9.disabled : ""} ${customProps.transparent ? styles$9.transparent : ""} ${!!context?.getName?.() ? styles$9.inFormField : ""} ${props?.class ?? ""}`;
1616
1706
  },
1617
1707
  get title() {
1618
1708
  return customProps.tooltip;
@@ -1724,8 +1814,8 @@ function Checkbox(props) {
1724
1814
  })();
1725
1815
  }
1726
1816
 
1727
- var css_248z$c = ".selectStyles-module_solid_select__placeholder__VO5-- {\n opacity: var(--text-emphasis-medium, 87%);\n transition: all 0.7s ease;\n}\n\n.selectStyles-module_solid_select__transparent__nOpvm {\n background-color: transparent;\n}\n\n.selectStyles-module_solid_select__3plh1 {\n display: inline-block;\n position: relative;\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n text-align: left;\n border-radius: 8px;\n width: 100%;\n margin: 0px 6px;\n}\n\n.selectStyles-module_solid_select__control__Wmmpg {\n display: flex;\n align-items: center;\n width: 100%;\n max-height: 48px;\n border-radius: 8px;\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n cursor: pointer;\n transition: border 0.7s ease, padding 0.7s ease;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.selectStyles-module_solid_select__control__Wmmpg:first-child {\n flex-grow: 1;\n}\n.selectStyles-module_solid_select__control__Wmmpg:last-child {\n padding: 0px 6px;\n margin: 0px;\n}\n\n.selectStyles-module_solid_select__control_no_form__Cq9Sc {\n display: flex;\n align-items: center;\n width: 100%;\n height: 48px;\n border-radius: 8px;\n width: 200px;\n margin-top: 2px;\n cursor: pointer;\n}\n.selectStyles-module_solid_select__control_no_form__Cq9Sc:first-child {\n flex-grow: 1;\n}\n.selectStyles-module_solid_select__control_no_form__Cq9Sc:last-child {\n padding: 0px 6px;\n margin: 0px;\n}\n\n.selectStyles-module_solid_select__arrow__OPCZo {\n font-size: 0.7em;\n}\n\n.selectStyles-module_solid_select__value__rNtqF {\n flex-grow: 1;\n transition: all 0.3s ease;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: block;\n}\n\n.selectStyles-module_multiselect-value__UUhhP {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 100%;\n}\n\n.selectStyles-module_solid_select__dropdown__UCt-N {\n position: absolute;\n background-color: var(--surface-color, #EEEEEE);\n top: 100%;\n left: 0;\n z-index: 999999999999999;\n max-height: 200px;\n border-radius: 8px;\n overflow-x: hidden;\n overflow-y: auto;\n box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);\n transform-origin: top;\n transform: scaleY(0);\n transition: transform 0.3s ease-out, opacity 0.3s ease-out;\n opacity: 0;\n}\n\n.selectStyles-module_dropTop__IVz9p {\n transform-origin: bottom;\n}\n\n.selectStyles-module_dropBottom__cYJF0 {\n transform-origin: top;\n}\n\n.selectStyles-module_open__f8zLA {\n transform: scaleY(1);\n opacity: 1;\n}\n\n.selectStyles-module_solid_select__option__47WMY {\n padding: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n min-height: 32px;\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n border-radius: 8px;\n}\n.selectStyles-module_solid_select__option__47WMY:hover {\n border: 2px inset var(--primary-color-varient, #43A047);\n}\n.selectStyles-module_solid_select__option__47WMY:has(.selectStyles-module_selected__1-CKm) {\n font-weight: bold;\n}\n\n.selectStyles-module_checkmark__UWcbd {\n display: inline-block;\n width: 1.2em;\n margin-right: 4px;\n text-align: center;\n}\n\n.selectStyles-module_option-label__bBFSW {\n width: -moz-max-content;\n width: max-content;\n height: -moz-max-content;\n height: max-content;\n}";
1728
- var styles$7 = {"solid_select__placeholder":"selectStyles-module_solid_select__placeholder__VO5--","solid_select__transparent":"selectStyles-module_solid_select__transparent__nOpvm","solid_select":"selectStyles-module_solid_select__3plh1","solid_select__control":"selectStyles-module_solid_select__control__Wmmpg","solid_select__control_no_form":"selectStyles-module_solid_select__control_no_form__Cq9Sc","solid_select__arrow":"selectStyles-module_solid_select__arrow__OPCZo","solid_select__value":"selectStyles-module_solid_select__value__rNtqF","multiselect-value":"selectStyles-module_multiselect-value__UUhhP","solid_select__dropdown":"selectStyles-module_solid_select__dropdown__UCt-N","dropTop":"selectStyles-module_dropTop__IVz9p","dropBottom":"selectStyles-module_dropBottom__cYJF0","open":"selectStyles-module_open__f8zLA","solid_select__option":"selectStyles-module_solid_select__option__47WMY","selected":"selectStyles-module_selected__1-CKm","checkmark":"selectStyles-module_checkmark__UWcbd","option-label":"selectStyles-module_option-label__bBFSW"};
1817
+ var css_248z$c = ".selectStyles-module_solid_select__placeholder__VO5-- {\n opacity: var(--text-emphasis-medium, 87%);\n transition: all 0.7s ease;\n}\n\n.selectStyles-module_solid_select__transparent__nOpvm {\n background-color: transparent;\n}\n\n.selectStyles-module_solid_select__3plh1 {\n display: inline-block;\n position: relative;\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n text-align: left;\n border-radius: 8px;\n width: 100%;\n margin: 0px 6px;\n}\n\n.selectStyles-module_solid_select__control__Wmmpg {\n display: flex;\n align-items: center;\n width: 100%;\n max-height: 48px;\n border-radius: 8px;\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n cursor: pointer;\n transition: border 0.7s ease, padding 0.7s ease;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.selectStyles-module_solid_select__control__Wmmpg:first-child {\n flex-grow: 1;\n}\n.selectStyles-module_solid_select__control__Wmmpg:last-child {\n padding: 0px 6px;\n margin: 0px;\n}\n\n.selectStyles-module_solid_select__control_no_form__Cq9Sc {\n display: flex;\n align-items: center;\n width: 100%;\n height: 48px;\n border-radius: 8px;\n width: 200px;\n margin-top: 2px;\n cursor: pointer;\n}\n.selectStyles-module_solid_select__control_no_form__Cq9Sc:first-child {\n flex-grow: 1;\n}\n.selectStyles-module_solid_select__control_no_form__Cq9Sc:last-child {\n padding: 0px 6px;\n margin: 0px;\n}\n\n.selectStyles-module_solid_select__disabled__5rUz8 {\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.selectStyles-module_solid_select__arrow__OPCZo {\n font-size: 0.7em;\n}\n\n.selectStyles-module_solid_select__value__rNtqF {\n flex-grow: 1;\n transition: all 0.3s ease;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: block;\n}\n\n.selectStyles-module_multiselect-value__UUhhP {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 100%;\n}\n\n.selectStyles-module_solid_select__dropdown__UCt-N {\n position: absolute;\n background-color: var(--surface-color, #EEEEEE);\n top: 100%;\n left: 0;\n z-index: 999999999999999;\n max-height: 200px;\n border-radius: 8px;\n overflow-x: hidden;\n overflow-y: auto;\n box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);\n transform-origin: top;\n transform: scaleY(0);\n transition: transform 0.3s ease-out, opacity 0.3s ease-out;\n opacity: 0;\n}\n\n.selectStyles-module_dropTop__IVz9p {\n transform-origin: bottom;\n}\n\n.selectStyles-module_dropBottom__cYJF0 {\n transform-origin: top;\n}\n\n.selectStyles-module_open__f8zLA {\n transform: scaleY(1);\n opacity: 1;\n}\n\n.selectStyles-module_solid_select__option__47WMY {\n padding: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n min-height: 32px;\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n border-radius: 8px;\n}\n.selectStyles-module_solid_select__option__47WMY:hover {\n border: 2px inset var(--primary-color-varient, #43A047);\n}\n.selectStyles-module_solid_select__option__47WMY:has(.selectStyles-module_selected__1-CKm) {\n font-weight: bold;\n}\n\n.selectStyles-module_solid_select__option_highlight__hPSRL {\n border: 2px inset var(--primary-color-varient, #43A047);\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n}\n\n.selectStyles-module_solid_select__option_disabled__IZBcA {\n cursor: not-allowed;\n opacity: 0.6;\n pointer-events: none;\n}\n\n.selectStyles-module_checkmark__UWcbd {\n display: inline-block;\n width: 1.2em;\n margin-right: 4px;\n text-align: center;\n}\n\n.selectStyles-module_option-label__bBFSW {\n width: -moz-max-content;\n width: max-content;\n height: -moz-max-content;\n height: max-content;\n}\n\n.selectStyles-module_solid_select__mobile_backdrop__MQU3O {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 999999999999999;\n background-color: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: flex-end;\n justify-content: center;\n animation: selectStyles-module_mobileBackdropFadeIn__BMxpT 0.2s ease-out;\n}\n\n.selectStyles-module_solid_select__mobile_popup__-MO-i {\n position: relative;\n display: flex;\n flex-direction: column;\n width: 90vw;\n max-width: 400px;\n max-height: 60vh;\n border-radius: 16px 16px 0 0;\n background-color: var(--surface-color, #EEEEEE);\n color: var(--on-surface-color, #000000);\n overflow: hidden;\n box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.45);\n animation: selectStyles-module_mobileSlideUp__JlYpt 0.3s ease-out;\n}\n\n.selectStyles-module_solid_select__mobile_header__gpULA {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 16px;\n min-height: 48px;\n background-color: var(--surface-color, #EEEEEE);\n color: var(--on-surface-color, #000000);\n border-bottom: 1px solid var(--surface-color-variant, #ccc);\n flex-shrink: 0;\n}\n\n.selectStyles-module_solid_select__mobile_title__MNbIa {\n font-size: 18px;\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.selectStyles-module_solid_select__mobile_close__RgfaX {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: var(--on-surface-color, #000000);\n font-size: 18px;\n cursor: pointer;\n flex-shrink: 0;\n transition: background-color 0.15s ease;\n}\n.selectStyles-module_solid_select__mobile_close__RgfaX:hover {\n background-color: var(--surface-color-variant, #ccc);\n}\n.selectStyles-module_solid_select__mobile_close__RgfaX:active {\n background-color: var(--surface-color-variant, #ccc);\n}\n\n.selectStyles-module_solid_select__mobile_options__01rHy {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 8px 0;\n -webkit-overflow-scrolling: touch;\n}\n\n.selectStyles-module_solid_select__mobile_footer__U08m7 {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n padding: 8px 16px;\n min-height: 52px;\n background-color: var(--surface-color, #EEEEEE);\n border-top: 1px solid var(--surface-color-variant, #ccc);\n flex-shrink: 0;\n}\n\n.selectStyles-module_solid_select__mobile_done__Xp6Gu {\n padding: 8px 24px;\n border: none;\n border-radius: 8px;\n background-color: var(--primary-color, #4CAF50);\n color: var(--on-primary-color, #fff);\n font-size: 16px;\n font-weight: 500;\n cursor: pointer;\n transition: background-color 0.15s ease, box-shadow 0.15s ease;\n}\n.selectStyles-module_solid_select__mobile_done__Xp6Gu:hover {\n background-color: var(--primary-color-varient, #43A047);\n}\n.selectStyles-module_solid_select__mobile_done__Xp6Gu:active {\n box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.15);\n}\n\n@keyframes selectStyles-module_mobileBackdropFadeIn__BMxpT {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n@keyframes selectStyles-module_mobileSlideUp__JlYpt {\n from {\n transform: translateY(30%);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}";
1818
+ var styles$7 = {"solid_select__placeholder":"selectStyles-module_solid_select__placeholder__VO5--","solid_select__transparent":"selectStyles-module_solid_select__transparent__nOpvm","solid_select":"selectStyles-module_solid_select__3plh1","solid_select__control":"selectStyles-module_solid_select__control__Wmmpg","solid_select__control_no_form":"selectStyles-module_solid_select__control_no_form__Cq9Sc","solid_select__disabled":"selectStyles-module_solid_select__disabled__5rUz8","solid_select__arrow":"selectStyles-module_solid_select__arrow__OPCZo","solid_select__value":"selectStyles-module_solid_select__value__rNtqF","multiselect-value":"selectStyles-module_multiselect-value__UUhhP","solid_select__dropdown":"selectStyles-module_solid_select__dropdown__UCt-N","dropTop":"selectStyles-module_dropTop__IVz9p","dropBottom":"selectStyles-module_dropBottom__cYJF0","open":"selectStyles-module_open__f8zLA","solid_select__option":"selectStyles-module_solid_select__option__47WMY","selected":"selectStyles-module_selected__1-CKm","solid_select__option_highlight":"selectStyles-module_solid_select__option_highlight__hPSRL","solid_select__option_disabled":"selectStyles-module_solid_select__option_disabled__IZBcA","checkmark":"selectStyles-module_checkmark__UWcbd","option-label":"selectStyles-module_option-label__bBFSW","solid_select__mobile_backdrop":"selectStyles-module_solid_select__mobile_backdrop__MQU3O","mobileBackdropFadeIn":"selectStyles-module_mobileBackdropFadeIn__BMxpT","solid_select__mobile_popup":"selectStyles-module_solid_select__mobile_popup__-MO-i","mobileSlideUp":"selectStyles-module_mobileSlideUp__JlYpt","solid_select__mobile_header":"selectStyles-module_solid_select__mobile_header__gpULA","solid_select__mobile_title":"selectStyles-module_solid_select__mobile_title__MNbIa","solid_select__mobile_close":"selectStyles-module_solid_select__mobile_close__RgfaX","solid_select__mobile_options":"selectStyles-module_solid_select__mobile_options__01rHy","solid_select__mobile_footer":"selectStyles-module_solid_select__mobile_footer__U08m7","solid_select__mobile_done":"selectStyles-module_solid_select__mobile_done__Xp6Gu"};
1729
1819
  styleInject(css_248z$c);
1730
1820
 
1731
1821
  const manager = new class WinManager {
@@ -1814,20 +1904,191 @@ const SelectContextProvider = props => {
1814
1904
  });
1815
1905
  };
1816
1906
 
1907
+ /**
1908
+ * Manages the registry of options for a Select component.
1909
+ * Handles registration, unregistration, ordering, and label resolution.
1910
+ */
1911
+ function useSelectOptions() {
1912
+ const [options, setOptions] = createStore({});
1913
+ const [optionOrder, setOptionOrder] = createSignal([]);
1914
+ const registerOption = (val, label, labelText = "") => {
1915
+ const stringVal = JSON.stringify(val);
1916
+ setOptions(store => ({
1917
+ ...store,
1918
+ [stringVal]: {
1919
+ value: stringVal,
1920
+ raw: val,
1921
+ label,
1922
+ labelText
1923
+ }
1924
+ }));
1925
+ setOptionOrder(prev => prev.includes(stringVal) ? prev : [...prev, stringVal]);
1926
+ };
1927
+ const unregisterOption = val => {
1928
+ const stringVal = JSON.stringify(val);
1929
+ setOptions(store => {
1930
+ const newStore = {
1931
+ ...store
1932
+ };
1933
+ delete newStore[stringVal];
1934
+ return newStore;
1935
+ });
1936
+ setOptionOrder(prev => prev.filter(key => key !== stringVal));
1937
+ };
1938
+ const optionEntries = createMemo(() => optionOrder().map(key => options[key]).filter(entry => !!entry));
1939
+ const getOptionLabelText = entry => {
1940
+ if (!entry) return "";
1941
+ const text = entry.labelText?.trim();
1942
+ if (text) return text;
1943
+ if (typeof entry.label === "string" || typeof entry.label === "number") return String(entry.label);
1944
+ return String(entry.raw ?? entry.value ?? "").trim();
1945
+ };
1946
+ const getLabel = val => {
1947
+ const stringVal = JSON.stringify(val);
1948
+ return options[stringVal]?.label || String(val);
1949
+ };
1950
+ return {
1951
+ options,
1952
+ registerOption,
1953
+ unregisterOption,
1954
+ optionEntries,
1955
+ getOptionLabelText,
1956
+ getLabel
1957
+ };
1958
+ }
1959
+
1960
+ /**
1961
+ * Manages highlighted-index state for keyboard navigation in a Select dropdown.
1962
+ * Provides movement, scroll-into-view, and reset-to-selected helpers.
1963
+ */
1964
+ function useHighlight(config) {
1965
+ const [highlightedIndex, setHighlightedIndex] = createSignal(-1);
1966
+ const scrollHighlightedIntoView = index => {
1967
+ const dropdown = config.dropdownRef();
1968
+ if (!dropdown) return;
1969
+ const optionsEls = dropdown.querySelectorAll('[role="option"]');
1970
+ const idx = index ?? highlightedIndex();
1971
+ const el = optionsEls[idx];
1972
+ if (el && typeof el.scrollIntoView === "function") {
1973
+ el.scrollIntoView({
1974
+ block: "nearest"
1975
+ });
1976
+ }
1977
+ };
1978
+ const moveHighlight = delta => {
1979
+ const entries = config.optionEntries();
1980
+ if (!entries.length) return;
1981
+ const nextIndex = ((highlightedIndex() < 0 ? 0 : highlightedIndex()) + delta + entries.length) % entries.length;
1982
+ setHighlightedIndex(nextIndex);
1983
+ queueMicrotask(() => scrollHighlightedIntoView(nextIndex));
1984
+ };
1985
+ const setHighlightToSelectedOrFirst = () => {
1986
+ const entries = config.optionEntries();
1987
+ if (!entries.length) {
1988
+ setHighlightedIndex(-1);
1989
+ return;
1990
+ }
1991
+ let idx = entries.findIndex(entry => config.isSelected(entry.raw));
1992
+ if (idx < 0) idx = 0;
1993
+ setHighlightedIndex(idx);
1994
+ queueMicrotask(() => scrollHighlightedIntoView(idx));
1995
+ };
1996
+ // Clamp highlighted index when entries change
1997
+ createEffect(() => {
1998
+ const entries = config.optionEntries();
1999
+ if (!entries.length) {
2000
+ if (highlightedIndex() !== -1) setHighlightedIndex(-1);
2001
+ return;
2002
+ }
2003
+ if (highlightedIndex() >= entries.length) {
2004
+ setHighlightedIndex(entries.length - 1);
2005
+ }
2006
+ });
2007
+ return {
2008
+ highlightedIndex,
2009
+ setHighlightedIndex,
2010
+ moveHighlight,
2011
+ setHighlightToSelectedOrFirst,
2012
+ scrollHighlightedIntoView
2013
+ };
2014
+ }
2015
+
2016
+ const TYPEAHEAD_TIMEOUT = 650;
2017
+ /**
2018
+ * Typeahead search for Select. Buffers keystrokes and finds
2019
+ * the first option whose label starts with the typed string.
2020
+ */
2021
+ function useTypeahead(config) {
2022
+ const [typeahead, setTypeahead] = createSignal("");
2023
+ let timeoutId;
2024
+ let lastTypeaheadAt = 0;
2025
+ const resetTypeahead = () => {
2026
+ setTypeahead("");
2027
+ if (timeoutId) {
2028
+ window.clearTimeout(timeoutId);
2029
+ timeoutId = undefined;
2030
+ }
2031
+ };
2032
+ const findMatchIndex = search => {
2033
+ const entries = config.optionEntries();
2034
+ if (!entries.length) return -1;
2035
+ const normalized = search.toLowerCase();
2036
+ const start = config.highlightedIndex() >= 0 ? (config.highlightedIndex() + 1) % entries.length : 0;
2037
+ for (let i = 0; i < entries.length; i += 1) {
2038
+ const idx = (start + i) % entries.length;
2039
+ const label = config.getOptionLabelText(entries[idx]).toLowerCase();
2040
+ if (label.startsWith(normalized)) return idx;
2041
+ }
2042
+ return -1;
2043
+ };
2044
+ const handleTypeahead = key => {
2045
+ const now = Date.now();
2046
+ const prev = typeahead();
2047
+ const isRepeat = prev.length === 1 && prev === key && now - lastTypeaheadAt < TYPEAHEAD_TIMEOUT;
2048
+ const nextBuffer = isRepeat ? key : `${prev}${key}`;
2049
+ lastTypeaheadAt = now;
2050
+ setTypeahead(nextBuffer);
2051
+ if (timeoutId) window.clearTimeout(timeoutId);
2052
+ timeoutId = window.setTimeout(() => setTypeahead(""), TYPEAHEAD_TIMEOUT);
2053
+ const matchIndex = findMatchIndex(nextBuffer);
2054
+ if (matchIndex >= 0) {
2055
+ config.onMatch(matchIndex);
2056
+ }
2057
+ };
2058
+ onCleanup(() => {
2059
+ if (timeoutId) {
2060
+ window.clearTimeout(timeoutId);
2061
+ }
2062
+ });
2063
+ return {
2064
+ handleTypeahead,
2065
+ resetTypeahead
2066
+ };
2067
+ }
2068
+
1817
2069
  var _tmpl$$g = /*#__PURE__*/template(`<span>`),
1818
2070
  _tmpl$2$8 = /*#__PURE__*/template(`<span>▲`),
1819
- _tmpl$3$2 = /*#__PURE__*/template(`<span>▼`),
1820
- _tmpl$4$1 = /*#__PURE__*/template(`<div>`),
1821
- _tmpl$5$1 = /*#__PURE__*/template(`<div is=coles-solid-select role=button aria-haspopup=listbox tabindex=0><div><span>`, true, false, false);
2071
+ _tmpl$3$3 = /*#__PURE__*/template(`<span>▼`),
2072
+ _tmpl$4$2 = /*#__PURE__*/template(`<div>`),
2073
+ _tmpl$5$1 = /*#__PURE__*/template(`<div><button type=button>Done`),
2074
+ _tmpl$6$1 = /*#__PURE__*/template(`<div><div role=dialog aria-modal=true tabindex=-1><div><span></span><button type=button aria-label=Close>✕</button></div><div role=listbox>`),
2075
+ _tmpl$7$1 = /*#__PURE__*/template(`<div is=coles-solid-select role=button tabindex=0><div><span>`, true, false, false);
1822
2076
  function Select(props) {
1823
- const isMultiple = Object.keys(props).includes("multiple") || props.multiple === true;
1824
- const [placeholder, setPlaceholder] = createSignal(props?.placeholder ?? "Select...");
1825
- // Internal state for selected value(s). Use provided value or defaultValue or an initial default.
2077
+ const isMultiple = props.multiple !== undefined || props.multiple === true;
1826
2078
  const [currStyle, setCurrStyle] = createSignal("primary");
1827
2079
  const defaultSelected = isMultiple ? props.value ?? props.defaultValue ?? [] : props.value ?? props.defaultValue ?? undefined;
1828
2080
  const [selected, setSelected] = createSignal(defaultSelected);
1829
2081
  const [selectRef, setSelectRef] = createSignal();
1830
2082
  const [dropdownRef, setDropdownRef] = createSignal();
2083
+ const [mobilePopupRef, setMobilePopupRef] = createSignal();
2084
+ // Resolved rendering mode: 'popup' for fullscreen mobile popup, 'desktop' for traditional dropdown
2085
+ const resolvedMode = createMemo(() => {
2086
+ const mode = props.mobileMode ?? 'auto';
2087
+ if (mode === 'popup') return 'popup';
2088
+ if (mode === 'desktop') return 'desktop';
2089
+ // 'auto': detect mobile at runtime
2090
+ return isMobile() ? 'popup' : 'desktop';
2091
+ });
1831
2092
  const form = useFormProvider();
1832
2093
  const formContext = useFormContext();
1833
2094
  const hasForm = !!form?.formName || !!form?.getName || !!form?.getValue || !!form?.setValue || !!form?.getTextInside;
@@ -1843,46 +2104,69 @@ function Select(props) {
1843
2104
  };
1844
2105
  // Signal for dropdown open/closed
1845
2106
  const [open, setOpen] = createSignal(false);
2107
+ const [menuRect, setMenuRect] = createSignal();
2108
+ const isDisabled = () => {
2109
+ const fieldset = form?.getFormFieldRef?.();
2110
+ const fieldsetDisabled = !!fieldset?.hasAttribute?.('disabled');
2111
+ return !!props.disabled || fieldsetDisabled;
2112
+ };
1846
2113
  const menuLocRef = createMemo(() => {
1847
2114
  if (!!form?.getFormFieldRef) {
1848
2115
  return form.getFormFieldRef();
1849
2116
  }
1850
2117
  return selectRef();
1851
2118
  });
1852
- const [options, setOptions] = createStore({});
1853
- // Register and unregister functions using the store
1854
- const registerOption = (val, label) => {
1855
- const stringVal = JSON.stringify(val);
1856
- setOptions(store => ({
1857
- ...store,
1858
- [stringVal]: {
1859
- value: stringVal,
1860
- label
1861
- }
1862
- }));
1863
- };
1864
- const unregisterOption = val => {
1865
- const stringVal = JSON.stringify(val);
1866
- setOptions(store => {
1867
- const newStore = {
1868
- ...store
1869
- };
1870
- delete newStore[stringVal];
1871
- return newStore;
1872
- });
1873
- };
1874
- const getLabel = val => {
1875
- const stringVal = JSON.stringify(val);
1876
- return options[stringVal]?.label || String(val);
1877
- };
2119
+ // --- Option registry (extracted hook) ---
2120
+ const {
2121
+ options,
2122
+ registerOption,
2123
+ unregisterOption,
2124
+ optionEntries,
2125
+ getOptionLabelText,
2126
+ getLabel
2127
+ } = useSelectOptions();
1878
2128
  // Helper to check if a value is selected (for Option highlighting)
1879
2129
  const isSelected = val => {
1880
2130
  const current = currentValue();
1881
2131
  return isMultiple ? Array.isArray(current) && current.includes(val) : current === val;
1882
2132
  };
2133
+ // --- Highlight management (extracted hook) ---
2134
+ // Use combined ref so scrollIntoView works in both desktop dropdown and mobile popup modes
2135
+ const activeListRef = createMemo(() => resolvedMode() === 'popup' ? mobilePopupRef() : dropdownRef());
2136
+ const {
2137
+ highlightedIndex,
2138
+ setHighlightedIndex,
2139
+ moveHighlight,
2140
+ setHighlightToSelectedOrFirst,
2141
+ scrollHighlightedIntoView
2142
+ } = useHighlight({
2143
+ optionEntries,
2144
+ isSelected,
2145
+ dropdownRef: activeListRef
2146
+ });
2147
+ // --- Typeahead search (extracted hook) ---
2148
+ const {
2149
+ handleTypeahead,
2150
+ resetTypeahead
2151
+ } = useTypeahead({
2152
+ optionEntries,
2153
+ highlightedIndex,
2154
+ getOptionLabelText,
2155
+ onMatch: index => {
2156
+ setHighlightedIndex(index);
2157
+ queueMicrotask(() => scrollHighlightedIntoView(index));
2158
+ }
2159
+ });
2160
+ // --- Overlay positioning (extracted hook) ---
2161
+ const {
2162
+ dropTop} = useOverlayPosition(menuLocRef, dropdownRef, open);
1883
2163
  // Function to handle selecting/toggling an option for single or multi-select
1884
2164
  // When not using a form or greater FormContext
1885
2165
  const selectValue = val => {
2166
+ if (form?.formName && formContext?.formGroup?.markDirty) {
2167
+ const meta = formContext.formGroup.getMeta(form?.formName);
2168
+ if (meta && !meta.dirty) formContext.formGroup.markDirty(form?.formName);
2169
+ }
1886
2170
  if (isMultiple) {
1887
2171
  // For multi-select, toggle the value in the array
1888
2172
  const current = props?.value ?? [];
@@ -1904,7 +2188,7 @@ function Select(props) {
1904
2188
  };
1905
2189
  // Compute the content to display in the closed select (trigger area)
1906
2190
  const displayValue = createMemo(() => {
1907
- const current = currentValue(); //selected();
2191
+ const current = currentValue();
1908
2192
  if (isMultiple) {
1909
2193
  const selectedArray = Array.isArray(current) ? current : [];
1910
2194
  if (selectedArray.length === 0) {
@@ -1965,149 +2249,19 @@ function Select(props) {
1965
2249
  }
1966
2250
  }
1967
2251
  });
1968
- const VIEWPORT_MARGIN = 4; // minimal gap from screen edges
1969
- const getDropdownMetrics = () => {
1970
- const dr = dropdownRef();
1971
- if (!dr) return {
1972
- height: 0,
1973
- width: 0
1974
- };
1975
- const rect = dr.getBoundingClientRect();
1976
- // When scaled closed, height can be 0; fallback to scrollHeight
1977
- const height = rect.height === 0 ? dr.scrollHeight || rect.height : rect.height;
1978
- return {
1979
- height,
1980
- width: rect.width
1981
- };
1982
- };
1983
- const dropdownBelowScreen = () => {
1984
- const menuLoc = menuLocRef();
1985
- if (menuLoc && dropdownRef()) {
1986
- const selectRect = menuLoc.getBoundingClientRect();
1987
- const {
1988
- height
1989
- } = getDropdownMetrics();
1990
- return selectRect.bottom + height + VIEWPORT_MARGIN > window.innerHeight && selectRect.top - height - VIEWPORT_MARGIN >= 0 ? true : selectRect.bottom + height + VIEWPORT_MARGIN > window.innerHeight;
1991
- }
1992
- return false;
1993
- };
1994
- const [menuRect, setMenuRect] = createSignal();
1995
- const selectLocation = createMemo(() => {
1996
- const select = selectRef();
1997
- const menuLoc = menuLocRef();
1998
- const getLocation = rect => {
1999
- if (dropdownBelowScreen()) {
2000
- return {
2001
- x: rect.left,
2002
- y: rect.top - rect.height
2003
- };
2004
- }
2005
- return {
2006
- x: rect.left,
2007
- y: rect.bottom
2008
- };
2009
- };
2010
- if (hasForm || hasFormContext) {
2011
- if (menuLoc) {
2012
- const rect = menuRect() ?? menuLoc.getBoundingClientRect();
2013
- return getLocation(rect);
2014
- } else if (select) {
2015
- const rect = select.getBoundingClientRect();
2016
- return getLocation(rect);
2017
- }
2018
- } else {
2019
- if (select) {
2020
- const rect = select.getBoundingClientRect();
2021
- return getLocation(rect);
2022
- }
2023
- }
2024
- return {
2025
- x: 0,
2026
- y: 0
2027
- };
2028
- });
2029
- const selectWidth = () => {
2030
- if (menuLocRef()) {
2031
- return menuLocRef().getBoundingClientRect().width;
2032
- }
2033
- return 0;
2034
- };
2035
- createMemo(() => {
2036
- const value = currentValue();
2037
- if (isMultiple) {
2038
- const selectedArray = Array.isArray(value) ? value : [];
2039
- if (selectedArray.length === 0) {
2040
- return 0;
2041
- }
2042
- const labels = selectedArray.map(val => options[JSON.stringify(val)]?.label || String(val));
2043
- return labels.join(", ").length * 8; // Approximate width based on character count
2044
- } else {
2045
- return selectWidth();
2046
- }
2047
- });
2048
- const updatePosition = () => {
2252
+ // --- Width sync effect ---
2253
+ createEffect(() => {
2049
2254
  const dropdown = dropdownRef();
2050
2255
  const select = selectRef();
2051
- const anchor = menuLocRef();
2052
- if (!dropdown || !(select || anchor)) return;
2053
- const baseRect = (anchor ?? select).getBoundingClientRect();
2054
- const {
2055
- height: ddHeight
2056
- } = getDropdownMetrics();
2057
- const spaceBelow = window.innerHeight - baseRect.bottom;
2058
- const spaceAbove = baseRect.top;
2059
- // Decide orientation: prefer below if it fits fully else choose the side with more space.
2060
- let placeAbove = false;
2061
- if (ddHeight + VIEWPORT_MARGIN <= spaceBelow) {
2062
- placeAbove = false;
2063
- } else if (ddHeight + VIEWPORT_MARGIN <= spaceAbove) {
2064
- placeAbove = true;
2065
- } else {
2066
- // Neither fits: pick side with more space
2067
- placeAbove = spaceAbove > spaceBelow;
2068
- }
2069
- // store orientation for class assignment
2070
- setDropTop(placeAbove);
2071
- // Compute available vertical space for dropdown and clamp to a sensible minimum
2072
- const availableSpace = (placeAbove ? spaceAbove : spaceBelow) - VIEWPORT_MARGIN;
2073
- const maxHeight = Math.max(160, availableSpace); // ensure at least 160px so a few options are visible
2074
- let newY;
2075
- if (!placeAbove) {
2076
- newY = baseRect.bottom + window.scrollY; // default below
2077
- // Clamp if overflow
2078
- if (newY + ddHeight + VIEWPORT_MARGIN > window.scrollY + window.innerHeight) {
2079
- newY = window.scrollY + window.innerHeight - ddHeight - VIEWPORT_MARGIN;
2080
- }
2081
- } else {
2082
- newY = baseRect.top + window.scrollY - ddHeight; // above
2083
- if (newY < window.scrollY + VIEWPORT_MARGIN) {
2084
- newY = window.scrollY + VIEWPORT_MARGIN;
2085
- }
2086
- }
2087
- // Final guard: ensure dropdown not negative even for huge heights
2088
- if (newY < window.scrollY + VIEWPORT_MARGIN) {
2089
- newY = window.scrollY + VIEWPORT_MARGIN;
2090
- }
2091
- const newX = baseRect.left + window.scrollX;
2092
- dropdown.style.left = `${newX}px`;
2093
- dropdown.style.top = `${newY}px`;
2094
- dropdown.style.width = `${baseRect.width}px`;
2095
- dropdown.style.maxHeight = `${maxHeight}px`;
2096
- };
2097
- // Update width of select to match option text width
2098
- createEffect(() => {
2099
- if (selectRef() && dropdownRef()) {
2100
- const dropdownWidth = dropdownRef().getBoundingClientRect().width;
2101
- const selectWidth = selectRef().getBoundingClientRect().width;
2256
+ if (select && dropdown) {
2257
+ const dropdownWidth = dropdown.getBoundingClientRect().width;
2258
+ const selectWidth = select.getBoundingClientRect().width;
2102
2259
  if (dropdownWidth !== selectWidth) {
2103
- setDropdownRef(old => {
2104
- if (!old) return;
2105
- old.style.width = `${selectWidth}px`;
2106
- return old;
2107
- });
2260
+ dropdown.style.width = `${selectWidth}px`;
2108
2261
  }
2109
2262
  }
2110
2263
  });
2264
+ // --- Form sync effects ---
2111
2265
  createEffect(() => {
2112
2266
  if (hasFormContext) {
2113
2267
  const value = currentValue();
@@ -2120,13 +2274,16 @@ function Select(props) {
2120
2274
  form.setValue?.(value);
2121
2275
  }
2122
2276
  });
2123
- const isTransparent = Object.keys(props).includes("transparent") || props.transparent === true;
2277
+ const isTransparent = props.transparent !== undefined || props.transparent === true;
2124
2278
  const styleClassTransparent = isTransparent ? "solid_select__transparent" : "";
2125
2279
  // Give Current Value to Props
2126
2280
  createEffect(() => {
2127
2281
  !!props?.onChange ? props.onChange(currentValue()) : null;
2128
2282
  });
2129
2283
  useClickOutside([dropdownRef, selectRef], () => {
2284
+ if (isDisabled()) return;
2285
+ // Desktop mode uses click-outside; mobile popup uses backdrop tap
2286
+ if (resolvedMode() === 'popup') return;
2130
2287
  setOpen(false);
2131
2288
  form?.setFocused?.(prev => {
2132
2289
  if (prev) {
@@ -2166,62 +2323,201 @@ function Select(props) {
2166
2323
  if (dropdown) {
2167
2324
  ignoreWindowManager(dropdown);
2168
2325
  }
2169
- document.addEventListener('scroll', updatePosition, true);
2170
- window.addEventListener('resize', updatePosition);
2171
- onCleanup(() => {
2172
- document.removeEventListener('scroll', updatePosition, true);
2173
- window.removeEventListener('resize', updatePosition);
2174
- });
2175
2326
  });
2327
+ // --- Mobile popup window manager lifecycle ---
2328
+ const closeMobilePopup = () => {
2329
+ setOpen(false);
2330
+ form?.setFocused?.(prev => {
2331
+ if (prev) {
2332
+ formContext?.formGroup?.validate?.(form?.formName ?? '');
2333
+ }
2334
+ return false;
2335
+ });
2336
+ };
2176
2337
  children(() => props.children);
2338
+ const selectLocation = createMemo(() => {
2339
+ const select = selectRef();
2340
+ const menuLoc = menuLocRef();
2341
+ const getLocation = rect => {
2342
+ if (dropTop()) {
2343
+ return {
2344
+ x: rect.left,
2345
+ y: rect.top - rect.height
2346
+ };
2347
+ }
2348
+ return {
2349
+ x: rect.left,
2350
+ y: rect.bottom
2351
+ };
2352
+ };
2353
+ if (hasForm || hasFormContext) {
2354
+ if (menuLoc) {
2355
+ const rect = menuRect() ?? menuLoc.getBoundingClientRect();
2356
+ return getLocation(rect);
2357
+ } else if (select) {
2358
+ const rect = select.getBoundingClientRect();
2359
+ return getLocation(rect);
2360
+ }
2361
+ } else {
2362
+ if (select) {
2363
+ const rect = select.getBoundingClientRect();
2364
+ return getLocation(rect);
2365
+ }
2366
+ }
2367
+ return {
2368
+ x: 0,
2369
+ y: 0
2370
+ };
2371
+ });
2177
2372
  const selectDropX = createMemo(() => `${selectLocation().x}px`);
2178
2373
  const selectDropY = createMemo(() => `${selectLocation().y}px`);
2374
+ // --- Open/close effects ---
2179
2375
  createEffect(() => {
2180
2376
  if (open()) {
2181
- // Wait a tick so dropdown renders before measuring
2182
- queueMicrotask(() => updatePosition());
2377
+ setHighlightToSelectedOrFirst();
2378
+ // Auto-focus mobile popup for keyboard interaction
2379
+ if (resolvedMode() === 'popup') {
2380
+ queueMicrotask(() => mobilePopupRef()?.focus());
2381
+ }
2382
+ } else {
2383
+ setHighlightedIndex(-1);
2384
+ resetTypeahead();
2385
+ }
2386
+ });
2387
+ createEffect(() => {
2388
+ if (props.disabled) {
2389
+ setOpen(false);
2183
2390
  }
2184
2391
  });
2392
+ // --- Context provider value ---
2185
2393
  const providerValue = createMemo(() => ({
2186
2394
  isSelected,
2187
2395
  selectValue,
2188
2396
  registerOption,
2189
2397
  unregisterOption,
2398
+ isHighlighted: val => {
2399
+ const stringVal = JSON.stringify(val);
2400
+ const entries = optionEntries();
2401
+ const index = entries.findIndex(entry => entry.value === stringVal);
2402
+ return index >= 0 && index === highlightedIndex();
2403
+ },
2190
2404
  selectRef,
2191
- selectStyle: currStyle
2405
+ selectStyle: currStyle,
2406
+ isDisabled,
2407
+ closeDropdown: () => {
2408
+ if (!isMultiple) setOpen(false);
2409
+ }
2192
2410
  }));
2193
- const [dropTop, setDropTop] = createSignal(false);
2194
- return (() => {
2195
- var _el$7 = _tmpl$5$1(),
2196
- _el$8 = _el$7.firstChild,
2197
- _el$9 = _el$8.firstChild;
2198
- _el$7.$$keydown = e => {
2199
- if (e.key === "ArrowDown") {
2200
- // Open dropdown if not open and set highlightedIndex to 0
2201
- if (!open()) {
2202
- setOpen(true);
2203
- // set highlightedIndex(0);
2411
+ // --- Keyboard handler ---
2412
+ const handleKeyDown = e => {
2413
+ if (isDisabled()) return;
2414
+ if (e.key === "Tab") {
2415
+ setOpen(false);
2416
+ return;
2417
+ }
2418
+ if (e.key === "ArrowDown") {
2419
+ e.preventDefault();
2420
+ if (!open()) {
2421
+ setOpen(true);
2422
+ setHighlightToSelectedOrFirst();
2423
+ } else {
2424
+ moveHighlight(1);
2425
+ }
2426
+ } else if (e.key === "ArrowUp") {
2427
+ e.preventDefault();
2428
+ if (!open()) {
2429
+ setOpen(true);
2430
+ setHighlightToSelectedOrFirst();
2431
+ } else {
2432
+ moveHighlight(-1);
2433
+ }
2434
+ } else if (e.key === "Home") {
2435
+ e.preventDefault();
2436
+ if (!open()) setOpen(true);
2437
+ if (optionEntries().length) {
2438
+ setHighlightedIndex(0);
2439
+ queueMicrotask(() => scrollHighlightedIntoView(0));
2440
+ }
2441
+ } else if (e.key === "End") {
2442
+ e.preventDefault();
2443
+ if (!open()) setOpen(true);
2444
+ const entries = optionEntries();
2445
+ if (entries.length) {
2446
+ const last = entries.length - 1;
2447
+ setHighlightedIndex(last);
2448
+ queueMicrotask(() => scrollHighlightedIntoView(last));
2449
+ }
2450
+ } else if (e.key === "Enter") {
2451
+ const entries = optionEntries();
2452
+ const idx = highlightedIndex();
2453
+ if (open() && entries.length && idx >= 0 && idx < entries.length) {
2454
+ e.preventDefault();
2455
+ const dropdown = dropdownRef();
2456
+ const optionEls = dropdown?.querySelectorAll('[role="option"]');
2457
+ const optionEl = optionEls?.[idx];
2458
+ if (optionEl) {
2459
+ optionEl.click();
2460
+ } else {
2461
+ selectValue(entries[idx].raw);
2204
2462
  }
2205
- } else if (e.key === "ArrowUp") ; else if (e.key === "Enter") ; else if (e.key === "Escape") {
2206
- setOpen(false);
2207
2463
  }
2208
- };
2209
- _el$7.$$click = e => {
2210
- // existing click logic below will toggle dropdown; ensure dirty marking once
2211
- if (form?.formName && formContext?.formGroup?.markDirty) {
2212
- const meta = formContext.formGroup.getMeta(form?.formName);
2213
- if (meta && !meta.dirty) formContext.formGroup.markDirty(form?.formName);
2464
+ } else if (e.key === "Escape") {
2465
+ setOpen(false);
2466
+ } else if (e.key.length === 1 && !e.metaKey && !e.ctrlKey && !e.altKey) {
2467
+ if (!open()) setOpen(true);
2468
+ e.preventDefault();
2469
+ handleTypeahead(e.key);
2470
+ }
2471
+ };
2472
+ // --- Mobile popup keyboard handler ---
2473
+ const mobilePopupTitle = createMemo(() => {
2474
+ const formLabel = form?.getName?.();
2475
+ if (formLabel && formLabel.trim()) return formLabel.trim();
2476
+ if (props.placeholder) return props.placeholder;
2477
+ return '';
2478
+ });
2479
+ const handleMobileKeyDown = e => {
2480
+ if (isDisabled()) return;
2481
+ if (e.key === "Escape") {
2482
+ closeMobilePopup();
2483
+ } else if (e.key === "ArrowDown") {
2484
+ e.preventDefault();
2485
+ moveHighlight(1);
2486
+ } else if (e.key === "ArrowUp") {
2487
+ e.preventDefault();
2488
+ moveHighlight(-1);
2489
+ } else if (e.key === "Enter") {
2490
+ const entries = optionEntries();
2491
+ const idx = highlightedIndex();
2492
+ if (entries.length && idx >= 0 && idx < entries.length) {
2493
+ e.preventDefault();
2494
+ const popup = mobilePopupRef();
2495
+ const optionEls = popup?.querySelectorAll('[role="option"]');
2496
+ const optionEl = optionEls?.[idx];
2497
+ if (optionEl) {
2498
+ optionEl.click();
2499
+ } else {
2500
+ selectValue(entries[idx].raw);
2501
+ }
2214
2502
  }
2215
- };
2503
+ } else if (e.key.length === 1 && !e.metaKey && !e.ctrlKey && !e.altKey) {
2504
+ e.preventDefault();
2505
+ handleTypeahead(e.key);
2506
+ }
2507
+ };
2508
+ return (() => {
2509
+ var _el$7 = _tmpl$7$1(),
2510
+ _el$8 = _el$7.firstChild,
2511
+ _el$9 = _el$8.firstChild;
2512
+ addEventListener(_el$7, "keydown", resolvedMode() === 'popup' ? undefined : handleKeyDown, true);
2216
2513
  _el$7.addEventListener("focus", () => {
2514
+ if (isDisabled()) return;
2217
2515
  form?.setFocused?.(true);
2218
- if (form?.formName && formContext?.formGroup?.markDirty) {
2219
- const meta = formContext.formGroup.getMeta(form?.formName);
2220
- if (meta && !meta.dirty) formContext.formGroup.markDirty(form?.formName);
2221
- }
2222
2516
  });
2223
2517
  _el$7._$owner = getOwner();
2224
2518
  _el$8.$$click = e => {
2519
+ if (isDisabled()) return;
2520
+ e.currentTarget?.parentElement?.focus?.();
2225
2521
  const menuRect = menuLocRef()?.getBoundingClientRect();
2226
2522
  setMenuRect(menuRect);
2227
2523
  setOpen(old => !old);
@@ -2243,7 +2539,7 @@ function Select(props) {
2243
2539
  return !open();
2244
2540
  },
2245
2541
  get children() {
2246
- var _el$11 = _tmpl$3$2();
2542
+ var _el$11 = _tmpl$3$3();
2247
2543
  createRenderEffect(() => className(_el$11, styles$7['solid_select__arrow']));
2248
2544
  return _el$11;
2249
2545
  }
@@ -2253,49 +2549,140 @@ function Select(props) {
2253
2549
  return providerValue();
2254
2550
  },
2255
2551
  get children() {
2256
- return createComponent(Portal, {
2552
+ return [createComponent(Show, {
2553
+ get when() {
2554
+ return resolvedMode() === 'desktop';
2555
+ },
2257
2556
  get children() {
2258
- var _el$12 = _tmpl$4$1();
2259
- use(setDropdownRef, _el$12);
2260
- insert(_el$12, () => props.children);
2261
- createRenderEffect(_p$ => {
2262
- var _v$ = `${styles$7['solid_select__dropdown']} ${dropTop() ? styles$7.dropTop : styles$7.dropBottom} ${open() ? styles$7.open : ''} ${props.dropdownClass || ""}`,
2263
- _v$2 = selectDropY(),
2264
- _v$3 = selectDropX(),
2265
- _v$4 = `${menuLocRef()?.getBoundingClientRect().width ?? 100}px !important`;
2266
- _v$ !== _p$.e && className(_el$12, _p$.e = _v$);
2267
- _v$2 !== _p$.t && ((_p$.t = _v$2) != null ? _el$12.style.setProperty("top", _v$2) : _el$12.style.removeProperty("top"));
2268
- _v$3 !== _p$.a && ((_p$.a = _v$3) != null ? _el$12.style.setProperty("left", _v$3) : _el$12.style.removeProperty("left"));
2269
- _v$4 !== _p$.o && ((_p$.o = _v$4) != null ? _el$12.style.setProperty("width", _v$4) : _el$12.style.removeProperty("width"));
2270
- return _p$;
2271
- }, {
2272
- e: undefined,
2273
- t: undefined,
2274
- a: undefined,
2275
- o: undefined
2557
+ return createComponent(Portal, {
2558
+ get children() {
2559
+ var _el$12 = _tmpl$4$2();
2560
+ use(setDropdownRef, _el$12);
2561
+ insert(_el$12, () => props.children);
2562
+ createRenderEffect(_p$ => {
2563
+ var _v$ = `${styles$7['solid_select__dropdown']} ${dropTop() ? styles$7.dropTop : styles$7.dropBottom} ${open() ? styles$7.open : ''} ${props.dropdownClass || ""}`,
2564
+ _v$2 = selectDropY(),
2565
+ _v$3 = selectDropX(),
2566
+ _v$4 = `${menuLocRef()?.getBoundingClientRect().width ?? 100}px !important`;
2567
+ _v$ !== _p$.e && className(_el$12, _p$.e = _v$);
2568
+ _v$2 !== _p$.t && ((_p$.t = _v$2) != null ? _el$12.style.setProperty("top", _v$2) : _el$12.style.removeProperty("top"));
2569
+ _v$3 !== _p$.a && ((_p$.a = _v$3) != null ? _el$12.style.setProperty("left", _v$3) : _el$12.style.removeProperty("left"));
2570
+ _v$4 !== _p$.o && ((_p$.o = _v$4) != null ? _el$12.style.setProperty("width", _v$4) : _el$12.style.removeProperty("width"));
2571
+ return _p$;
2572
+ }, {
2573
+ e: undefined,
2574
+ t: undefined,
2575
+ a: undefined,
2576
+ o: undefined
2577
+ });
2578
+ return _el$12;
2579
+ }
2276
2580
  });
2277
- return _el$12;
2278
2581
  }
2279
- });
2582
+ }), createComponent(Show, {
2583
+ get when() {
2584
+ return resolvedMode() === 'popup';
2585
+ },
2586
+ get children() {
2587
+ return createComponent(Portal, {
2588
+ get children() {
2589
+ return createComponent(Show, {
2590
+ get when() {
2591
+ return open();
2592
+ },
2593
+ get children() {
2594
+ var _el$13 = _tmpl$6$1(),
2595
+ _el$14 = _el$13.firstChild,
2596
+ _el$15 = _el$14.firstChild,
2597
+ _el$16 = _el$15.firstChild,
2598
+ _el$17 = _el$16.nextSibling,
2599
+ _el$18 = _el$15.nextSibling;
2600
+ _el$13.$$mousedown = e => {
2601
+ // Close when clicking the backdrop itself (outside the popup)
2602
+ if (e.target === e.currentTarget) {
2603
+ closeMobilePopup();
2604
+ }
2605
+ };
2606
+ use(el => ignoreWindowManager(el), _el$13);
2607
+ _el$14.$$keydown = handleMobileKeyDown;
2608
+ use(setMobilePopupRef, _el$14);
2609
+ insert(_el$16, mobilePopupTitle);
2610
+ _el$17.$$click = () => closeMobilePopup();
2611
+ insert(_el$18, () => props.children);
2612
+ insert(_el$14, createComponent(Show, {
2613
+ when: isMultiple,
2614
+ get children() {
2615
+ var _el$19 = _tmpl$5$1(),
2616
+ _el$20 = _el$19.firstChild;
2617
+ _el$20.$$click = () => closeMobilePopup();
2618
+ createRenderEffect(_p$ => {
2619
+ var _v$5 = styles$7['solid_select__mobile_footer'],
2620
+ _v$6 = styles$7['solid_select__mobile_done'];
2621
+ _v$5 !== _p$.e && className(_el$19, _p$.e = _v$5);
2622
+ _v$6 !== _p$.t && className(_el$20, _p$.t = _v$6);
2623
+ return _p$;
2624
+ }, {
2625
+ e: undefined,
2626
+ t: undefined
2627
+ });
2628
+ return _el$19;
2629
+ }
2630
+ }), null);
2631
+ createRenderEffect(_p$ => {
2632
+ var _v$7 = styles$7['solid_select__mobile_backdrop'],
2633
+ _v$8 = mobilePopupTitle() || undefined,
2634
+ _v$9 = `${styles$7['solid_select__mobile_popup']} ${props.dropdownClass || ""}`,
2635
+ _v$10 = styles$7['solid_select__mobile_header'],
2636
+ _v$11 = styles$7['solid_select__mobile_title'],
2637
+ _v$12 = styles$7['solid_select__mobile_close'],
2638
+ _v$13 = styles$7['solid_select__mobile_options'];
2639
+ _v$7 !== _p$.e && className(_el$13, _p$.e = _v$7);
2640
+ _v$8 !== _p$.t && setAttribute(_el$14, "aria-label", _p$.t = _v$8);
2641
+ _v$9 !== _p$.a && className(_el$14, _p$.a = _v$9);
2642
+ _v$10 !== _p$.o && className(_el$15, _p$.o = _v$10);
2643
+ _v$11 !== _p$.i && className(_el$16, _p$.i = _v$11);
2644
+ _v$12 !== _p$.n && className(_el$17, _p$.n = _v$12);
2645
+ _v$13 !== _p$.s && className(_el$18, _p$.s = _v$13);
2646
+ return _p$;
2647
+ }, {
2648
+ e: undefined,
2649
+ t: undefined,
2650
+ a: undefined,
2651
+ o: undefined,
2652
+ i: undefined,
2653
+ n: undefined,
2654
+ s: undefined
2655
+ });
2656
+ return _el$13;
2657
+ }
2658
+ });
2659
+ }
2660
+ });
2661
+ }
2662
+ })];
2280
2663
  }
2281
2664
  }), null);
2282
2665
  createRenderEffect(_p$ => {
2283
- var _v$5 = props.id,
2284
- _v$6 = `${styles$7.solid_select__control_no_form} ${styles$7[styleClassTransparent]} coles-solid-selectControl`,
2285
- _v$7 = open(),
2286
- _v$8 = props.tooltip,
2287
- _v$9 = `${styles$7['solid_select__control']} ${props.class || ""}`,
2288
- _v$10 = !hasForm ? {
2666
+ var _v$14 = props.id,
2667
+ _v$15 = `${styles$7.solid_select__control_no_form} ${styles$7[styleClassTransparent]} ${isDisabled() ? styles$7.solid_select__disabled : ''} coles-solid-selectControl`,
2668
+ _v$16 = resolvedMode() === 'popup' ? 'dialog' : 'listbox',
2669
+ _v$17 = isDisabled() ? false : open(),
2670
+ _v$18 = isDisabled(),
2671
+ _v$19 = props.tooltip,
2672
+ _v$20 = `${styles$7['solid_select__control']} ${props.class || ""} ${isDisabled() ? styles$7.solid_select__disabled : ''}`,
2673
+ _v$21 = !hasForm ? {
2289
2674
  height: '48px'
2290
2675
  } : {},
2291
- _v$11 = styles$7['solid_select__value'];
2292
- _v$5 !== _p$.e && (_el$7.id = _p$.e = _v$5);
2293
- _v$6 !== _p$.t && className(_el$7, _p$.t = _v$6);
2294
- _v$7 !== _p$.a && (_el$7.ariaExpanded = _p$.a = _v$7);
2295
- _v$8 !== _p$.o && (_el$7.title = _p$.o = _v$8);
2296
- _v$9 !== _p$.i && className(_el$8, _p$.i = _v$9);
2297
- _p$.n = style$9(_el$8, _v$10, _p$.n);
2298
- _v$11 !== _p$.s && className(_el$9, _p$.s = _v$11);
2676
+ _v$22 = styles$7['solid_select__value'];
2677
+ _v$14 !== _p$.e && (_el$7.id = _p$.e = _v$14);
2678
+ _v$15 !== _p$.t && className(_el$7, _p$.t = _v$15);
2679
+ _v$16 !== _p$.a && (_el$7.ariaHaspopup = _p$.a = _v$16);
2680
+ _v$17 !== _p$.o && (_el$7.ariaExpanded = _p$.o = _v$17);
2681
+ _v$18 !== _p$.i && (_el$7.ariaDisabled = _p$.i = _v$18);
2682
+ _v$19 !== _p$.n && (_el$7.title = _p$.n = _v$19);
2683
+ _v$20 !== _p$.s && className(_el$8, _p$.s = _v$20);
2684
+ _p$.h = style$9(_el$8, _v$21, _p$.h);
2685
+ _v$22 !== _p$.r && className(_el$9, _p$.r = _v$22);
2299
2686
  return _p$;
2300
2687
  }, {
2301
2688
  e: undefined,
@@ -2304,20 +2691,24 @@ function Select(props) {
2304
2691
  o: undefined,
2305
2692
  i: undefined,
2306
2693
  n: undefined,
2307
- s: undefined
2694
+ s: undefined,
2695
+ h: undefined,
2696
+ r: undefined
2308
2697
  });
2309
2698
  return _el$7;
2310
2699
  })();
2311
2700
  }
2312
- delegateEvents(["click", "keydown"]);
2701
+ delegateEvents(["keydown", "click", "mousedown"]);
2313
2702
 
2314
2703
  var _tmpl$$f = /*#__PURE__*/template(`<div role=option><span></span><span is=coles-select-label>`, true, false, false);
2315
2704
  function Option(props) {
2316
2705
  const formField = useFormProvider();
2317
2706
  const formContext = useFormContext();
2318
2707
  const select = useSelectContext();
2708
+ let labelRef;
2319
2709
  onMount(() => {
2320
- select.registerOption?.(props.value, props.children);
2710
+ const labelText = labelRef?.textContent?.trim() ?? (typeof props.children === "string" || typeof props.children === "number" ? String(props.children) : "");
2711
+ select.registerOption?.(props.value, props.children, labelText);
2321
2712
  });
2322
2713
  onCleanup(() => select.unregisterOption?.(props.value));
2323
2714
  const selectFormFieldValue = value => {
@@ -2375,13 +2766,17 @@ function Option(props) {
2375
2766
  return false;
2376
2767
  };
2377
2768
  const handleClick = e => {
2769
+ if (select?.isDisabled?.()) return;
2378
2770
  e.stopPropagation();
2379
2771
  const contextSuccess = selectFormContextValue(props.value);
2380
2772
  !contextSuccess ? selectFormFieldValue(props.value) : true;
2381
2773
  if (!formField?.getName?.()) {
2382
2774
  select.selectValue?.(props.value);
2383
- formField?.setFocused?.(true);
2775
+ } else {
2776
+ // Form handled the value — still need to close for single select
2777
+ select.closeDropdown?.();
2384
2778
  }
2779
+ formField?.setFocused?.(true);
2385
2780
  };
2386
2781
  return (() => {
2387
2782
  var _el$ = _tmpl$$f(),
@@ -2389,34 +2784,42 @@ function Option(props) {
2389
2784
  _el$3 = _el$2.nextSibling;
2390
2785
  _el$.$$click = handleClick;
2391
2786
  insert(_el$2, () => select?.isSelected?.(props.value) ?? false ? "✓" : "");
2787
+ var _ref$ = labelRef;
2788
+ typeof _ref$ === "function" ? use(_ref$, _el$3) : labelRef = _el$3;
2392
2789
  _el$3._$owner = getOwner();
2393
2790
  insert(_el$3, () => props.children ?? "");
2394
2791
  createRenderEffect(_p$ => {
2395
2792
  var _v$ = select?.isSelected?.(props.value) ?? false,
2396
- _v$2 = `${styles$7['solid_select__option']} ${props.class || ""}`,
2397
- _v$3 = !!(select?.isSelected?.(props.value) ?? false),
2398
- _v$4 = `${styles$7['checkmark']}`,
2399
- _v$5 = `${styles$7['option-label']}`;
2793
+ _v$2 = select?.isDisabled?.() ?? false,
2794
+ _v$3 = `${styles$7['solid_select__option']} ${props.class || ""} ${select?.isDisabled?.() ? styles$7.solid_select__option_disabled : ""}`,
2795
+ _v$4 = {
2796
+ "selected": select?.isSelected?.(props.value) ?? false,
2797
+ [styles$7.solid_select__option_highlight]: select?.isHighlighted?.(props.value) ?? false
2798
+ },
2799
+ _v$5 = `${styles$7['checkmark']}`,
2800
+ _v$6 = `${styles$7['option-label']}`;
2400
2801
  _v$ !== _p$.e && setAttribute(_el$, "aria-selected", _p$.e = _v$);
2401
- _v$2 !== _p$.t && className(_el$, _p$.t = _v$2);
2402
- _v$3 !== _p$.a && _el$.classList.toggle("selected", _p$.a = _v$3);
2403
- _v$4 !== _p$.o && className(_el$2, _p$.o = _v$4);
2404
- _v$5 !== _p$.i && className(_el$3, _p$.i = _v$5);
2802
+ _v$2 !== _p$.t && setAttribute(_el$, "aria-disabled", _p$.t = _v$2);
2803
+ _v$3 !== _p$.a && className(_el$, _p$.a = _v$3);
2804
+ _p$.o = classList(_el$, _v$4, _p$.o);
2805
+ _v$5 !== _p$.i && className(_el$2, _p$.i = _v$5);
2806
+ _v$6 !== _p$.n && className(_el$3, _p$.n = _v$6);
2405
2807
  return _p$;
2406
2808
  }, {
2407
2809
  e: undefined,
2408
2810
  t: undefined,
2409
2811
  a: undefined,
2410
2812
  o: undefined,
2411
- i: undefined
2813
+ i: undefined,
2814
+ n: undefined
2412
2815
  });
2413
2816
  return _el$;
2414
2817
  })();
2415
2818
  }
2416
2819
  delegateEvents(["click"]);
2417
2820
 
2418
- var css_248z$b = ".TextArea-module_areaStyle__AshKi {\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n padding: 0.5rem;\n margin-right: calc(var(--spacing-1, 8px) / 2);\n border: 1px solid #ccc;\n border-radius: var(--border-radius-md, 6px);\n width: 98%;\n height: 100%;\n resize: none;\n}\n@media screen and (max-width: 768px) {\n .TextArea-module_areaStyle__AshKi {\n width: 90%;\n }\n}\n.TextArea-module_areaStyle__AshKi::-moz-placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.TextArea-module_areaStyle__AshKi::placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n\n.TextArea-module_picButton__TV9ZE {\n padding: calc(var(--spacing-1, 8px) / 2) var(--spacing-1, 8px) !important;\n background-color: transparent;\n border-top: 1px solid white;\n border-bottom: 1px solid white;\n}\n\n.TextArea-module_transparent__pwXRO {\n background-color: transparent;\n border: none;\n color: white;\n padding: 0.5rem;\n width: inherit;\n height: 100%;\n resize: none;\n}\n.TextArea-module_transparent__pwXRO:focus {\n outline: none;\n border: none;\n}";
2419
- var style$4 = {"areaStyle":"TextArea-module_areaStyle__AshKi"};
2821
+ var css_248z$b = ".TextArea-module_areaStyle__AshKi {\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n padding: 0.5rem;\n margin-right: calc(var(--spacing-1, 8px) / 2);\n border: 1px solid #ccc;\n border-radius: var(--border-radius-md, 6px);\n width: 98%;\n height: 100%;\n resize: none;\n}\n@media screen and (max-width: 768px) {\n .TextArea-module_areaStyle__AshKi {\n width: 90%;\n }\n}\n.TextArea-module_areaStyle__AshKi::-moz-placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.TextArea-module_areaStyle__AshKi::placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n\n.TextArea-module_disabled__lHxCa {\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.TextArea-module_picButton__TV9ZE {\n padding: calc(var(--spacing-1, 8px) / 2) var(--spacing-1, 8px) !important;\n background-color: transparent;\n border-top: 1px solid white;\n border-bottom: 1px solid white;\n}\n\n.TextArea-module_transparent__pwXRO {\n background-color: transparent;\n border: none;\n color: white;\n padding: 0.5rem;\n width: inherit;\n height: 100%;\n resize: none;\n}\n.TextArea-module_transparent__pwXRO:focus {\n outline: none;\n border: none;\n}";
2822
+ var style$4 = {"areaStyle":"TextArea-module_areaStyle__AshKi","disabled":"TextArea-module_disabled__lHxCa"};
2420
2823
  styleInject(css_248z$b);
2421
2824
 
2422
2825
  var _tmpl$$e = /*#__PURE__*/template(`<textarea>`);
@@ -2480,6 +2883,7 @@ const TextArea = props => {
2480
2883
  queueMicrotask(resizeToContent);
2481
2884
  });
2482
2885
  const handleInput = e => {
2886
+ if (props.disabled) return;
2483
2887
  const newVal = e.currentTarget.value;
2484
2888
  // Update whichever source is active
2485
2889
  if (formName && formCtx?.formGroup) {
@@ -2507,7 +2911,7 @@ const TextArea = props => {
2507
2911
  return areaValue();
2508
2912
  },
2509
2913
  get ["class"]() {
2510
- return `${style$4.areaStyle} ${customProps.class ?? ''} ${customProps.transparent ? customProps.transparent : ''}`;
2914
+ return `${style$4.areaStyle} ${props.disabled ? style$4.disabled : ''} ${customProps.class ?? ''} ${customProps.transparent ? customProps.transparent : ''}`;
2511
2915
  },
2512
2916
  get placeholder() {
2513
2917
  return fieldCtx?.getTextInside?.() && !fieldCtx?.getFocused?.() ? '' : props.placeholder;
@@ -2517,6 +2921,7 @@ const TextArea = props => {
2517
2921
  },
2518
2922
  "onInput": handleInput,
2519
2923
  "onFocus": () => {
2924
+ if (props.disabled) return;
2520
2925
  fieldCtx?.setFocused?.(true);
2521
2926
  if (formName && formCtx?.formGroup?.markDirty) {
2522
2927
  const meta = formCtx.formGroup.getMeta(formName);
@@ -2524,12 +2929,16 @@ const TextArea = props => {
2524
2929
  }
2525
2930
  },
2526
2931
  "onClick": () => {
2932
+ if (props.disabled) return;
2527
2933
  if (formName && formCtx?.formGroup?.markDirty) {
2528
2934
  const meta = formCtx.formGroup.getMeta(formName);
2529
2935
  if (meta && !meta.dirty) formCtx.formGroup.markDirty(formName);
2530
2936
  }
2531
2937
  },
2532
- "onBlur": () => fieldCtx?.setFocused?.(false)
2938
+ "onBlur": () => {
2939
+ if (props.disabled) return;
2940
+ fieldCtx?.setFocused?.(false);
2941
+ }
2533
2942
  }), false, false);
2534
2943
  return _el$;
2535
2944
  })();
@@ -2540,13 +2949,20 @@ var style$3 = {"popup":"popup-module_popup__5A6Ji","wrapper":"popup-module_wrapp
2540
2949
  styleInject(css_248z$a);
2541
2950
 
2542
2951
  var _tmpl$$d = /*#__PURE__*/template(`<b>X`),
2543
- _tmpl$2$7 = /*#__PURE__*/template(`<div><div><div><h2></h2><span></span></div><div>`);
2952
+ _tmpl$2$7 = /*#__PURE__*/template(`<div><h2></h2><span>`),
2953
+ _tmpl$3$2 = /*#__PURE__*/template(`<div>`),
2954
+ _tmpl$4$1 = /*#__PURE__*/template(`<div><div>`);
2544
2955
  const Modal = props => {
2545
2956
  const defaultX = createMemo(() => props.translate?.x ?? "-50%");
2546
2957
  const defaultY = createMemo(() => props.translate?.y ?? "-50%");
2547
2958
  const isShown = createMemo(() => props.show[0]());
2548
2959
  const [innerPopup, setInnerPopup] = createSignal();
2549
2960
  // const [ignoreClicks, setIgnoreClicks] = createSignal(true);
2961
+ const showHeader = createMemo(() => {
2962
+ const hasKey = Object.keys(props).includes("noHeader");
2963
+ if (hasKey && props.noHeader === undefined) return false;
2964
+ return !props.noHeader;
2965
+ });
2550
2966
  // Maintain a stable entry reference so unregister removes the correct instance.
2551
2967
  let wmEntry;
2552
2968
  createEffect(() => {
@@ -2610,50 +3026,70 @@ const Modal = props => {
2610
3026
  get children() {
2611
3027
  return createComponent(Portal, {
2612
3028
  get children() {
2613
- var _el$ = _tmpl$2$7(),
2614
- _el$2 = _el$.firstChild,
2615
- _el$3 = _el$2.firstChild,
2616
- _el$4 = _el$3.firstChild,
2617
- _el$5 = _el$4.nextSibling,
2618
- _el$7 = _el$3.nextSibling;
3029
+ var _el$ = _tmpl$4$1(),
3030
+ _el$2 = _el$.firstChild;
2619
3031
  use(el => {
2620
3032
  setInnerPopup(el);
2621
3033
  // @ts-ignore
2622
3034
  props?.ref?.(el);
2623
3035
  }, _el$2);
2624
- insert(_el$4, () => props.title ?? "Modal");
2625
- insert(_el$5, createComponent(Button, {
2626
- transparent: true,
2627
- onClick: () => props.show[1](false),
3036
+ insert(_el$2, createComponent(Show, {
3037
+ get when() {
3038
+ return showHeader();
3039
+ },
2628
3040
  get children() {
2629
- return _tmpl$$d();
3041
+ return [(() => {
3042
+ var _el$3 = _tmpl$2$7(),
3043
+ _el$4 = _el$3.firstChild,
3044
+ _el$5 = _el$4.nextSibling;
3045
+ insert(_el$4, () => props.title ?? "Modal");
3046
+ insert(_el$5, createComponent(Button, {
3047
+ transparent: true,
3048
+ onClick: () => props.show[1](false),
3049
+ get children() {
3050
+ return _tmpl$$d();
3051
+ }
3052
+ }));
3053
+ createRenderEffect(() => className(_el$3, style$3.header));
3054
+ return _el$3;
3055
+ })(), (() => {
3056
+ var _el$7 = _tmpl$3$2();
3057
+ insert(_el$7, () => props.children);
3058
+ createRenderEffect(() => className(_el$7, style$3.body));
3059
+ return _el$7;
3060
+ })()];
2630
3061
  }
2631
- }));
2632
- insert(_el$7, () => props.children);
3062
+ }), null);
3063
+ insert(_el$2, createComponent(Show, {
3064
+ get when() {
3065
+ return !showHeader();
3066
+ },
3067
+ get children() {
3068
+ var _el$8 = _tmpl$3$2();
3069
+ _el$8.style.setProperty("height", "100%");
3070
+ insert(_el$8, () => props.children);
3071
+ createRenderEffect(() => className(_el$8, style$3.body));
3072
+ return _el$8;
3073
+ }
3074
+ }), null);
2633
3075
  createRenderEffect(_p$ => {
2634
3076
  var _v$ = style$3.backdrop,
2635
3077
  _v$2 = widthStyle(),
2636
3078
  _v$3 = heightStyle(),
2637
3079
  _v$4 = shouldTranslate(),
2638
- _v$5 = `${style$3["primary"]} ${style$3.wrapper} ${style$3.popup}`,
2639
- _v$6 = style$3.header,
2640
- _v$7 = style$3.body;
3080
+ _v$5 = `${style$3["primary"]} ${style$3.wrapper} ${style$3.popup}`;
2641
3081
  _v$ !== _p$.e && className(_el$, _p$.e = _v$);
2642
3082
  _v$2 !== _p$.t && ((_p$.t = _v$2) != null ? _el$2.style.setProperty("width", _v$2) : _el$2.style.removeProperty("width"));
2643
3083
  _v$3 !== _p$.a && ((_p$.a = _v$3) != null ? _el$2.style.setProperty("height", _v$3) : _el$2.style.removeProperty("height"));
2644
3084
  _v$4 !== _p$.o && ((_p$.o = _v$4) != null ? _el$2.style.setProperty("transform", _v$4) : _el$2.style.removeProperty("transform"));
2645
3085
  _v$5 !== _p$.i && className(_el$2, _p$.i = _v$5);
2646
- _v$6 !== _p$.n && className(_el$3, _p$.n = _v$6);
2647
- _v$7 !== _p$.s && className(_el$7, _p$.s = _v$7);
2648
3086
  return _p$;
2649
3087
  }, {
2650
3088
  e: undefined,
2651
3089
  t: undefined,
2652
3090
  a: undefined,
2653
3091
  o: undefined,
2654
- i: undefined,
2655
- n: undefined,
2656
- s: undefined
3092
+ i: undefined
2657
3093
  });
2658
3094
  return _el$;
2659
3095
  }
@@ -2956,7 +3392,7 @@ const useMenuContext = () => {
2956
3392
 
2957
3393
  var _tmpl$$7 = /*#__PURE__*/template(`<div><ul>`);
2958
3394
  const Menu = props => {
2959
- const [local, others] = splitProps(props, ['anchorElement', 'children', 'ref', 'show', 'position']);
3395
+ const [local, others] = splitProps(props, ['anchorElement', 'children', 'ref', 'show', 'position', 'listClass']);
2960
3396
  const [menuRef, setMenuRef] = createSignal();
2961
3397
  const menuContext = useMenuContext();
2962
3398
  const openStyle = () => {
@@ -3054,7 +3490,7 @@ const Menu = props => {
3054
3490
  }
3055
3491
  }), false, true);
3056
3492
  insert(_el$2, () => local.children);
3057
- createRenderEffect(() => className(_el$2, `${styles$4.list}`));
3493
+ createRenderEffect(() => className(_el$2, `${styles$4.list} ${local.listClass ?? ''}`));
3058
3494
  return _el$;
3059
3495
  }
3060
3496
  });
@@ -3077,7 +3513,7 @@ const MenuItem = props => {
3077
3513
 
3078
3514
  var _tmpl$$5 = /*#__PURE__*/template(`<li><span><span></span></span><ul>`);
3079
3515
  const MenuDropdown = props => {
3080
- const [local, others] = splitProps(props, ['children', 'class', 'header']);
3516
+ const [local, others] = splitProps(props, ['children', 'class', 'header', 'dropListClass']);
3081
3517
  const [isOpen, setIsOpen] = createSignal(false);
3082
3518
  const onButtonClick = e => {
3083
3519
  setIsOpen(old => {
@@ -3131,7 +3567,7 @@ const MenuDropdown = props => {
3131
3567
  createRenderEffect(_p$ => {
3132
3568
  var _v$ = `${styles$4.listHeader}`,
3133
3569
  _v$2 = `${styles$4.header}`,
3134
- _v$3 = `${styles$4.list} ${styles$4.droplist} ${isOpen() ? styles$4.openDropList : ''}`;
3570
+ _v$3 = `${styles$4.list} ${styles$4.droplist} ${isOpen() ? styles$4.openDropList : ''} ${local.dropListClass ?? ''}`;
3135
3571
  _v$ !== _p$.e && className(_el$2, _p$.e = _v$);
3136
3572
  _v$2 !== _p$.t && className(_el$3, _p$.t = _v$2);
3137
3573
  _v$3 !== _p$.a && className(_el$4, _p$.a = _v$3);
@@ -3690,7 +4126,7 @@ class FormArray {
3690
4126
  }
3691
4127
  }
3692
4128
 
3693
- var css_248z$2 = ".formfield-module_formField__w6mH9:focus-within > legend, .formfield-module_has-focus__9ingx > legend {\n top: -8px !important;\n font-size: 0.75rem !important;\n}\n\n.formfield-module_formField__w6mH9 {\n position: relative;\n display: inline-block;\n border-radius: var(--border-radius-md);\n box-sizing: border-box;\n border: none;\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n margin-top: 0px !important;\n margin-bottom: 0px !important;\n}\n.formfield-module_formField__w6mH9 > legend {\n position: absolute;\n left: 12px;\n top: calc(50% - 0.5em);\n font-size: 1rem;\n transition: top 0.25s ease, font-size 0.25s ease;\n pointer-events: none;\n}\n.formfield-module_formField__w6mH9 input::-moz-placeholder, .formfield-module_formField__w6mH9 select::-moz-placeholder {\n opacity: 0 !important;\n -moz-transition: opacity 0.25s ease;\n transition: opacity 0.25s ease;\n}\n.formfield-module_formField__w6mH9 input::placeholder,\n.formfield-module_formField__w6mH9 select::placeholder {\n opacity: 0 !important;\n transition: opacity 0.25s ease;\n}\n.formfield-module_formField__w6mH9 label {\n position: relative;\n top: -0.5rem;\n padding-right: 10px;\n}\n.formfield-module_formField__w6mH9:has(textarea) {\n position: relative;\n margin: 8px;\n}\n.formfield-module_formField__w6mH9:has(textarea) textarea {\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n width: auto;\n min-width: 95%;\n font-family: \"Roboto, sans-serif\";\n font-size: 16px;\n padding-bottom: 8px;\n border: none;\n}\n.formfield-module_formField__w6mH9:has(textarea) textarea:focus {\n outline: none;\n}\n.formfield-module_formField__w6mH9:has(textarea) textarea::-moz-placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_formField__w6mH9:has(textarea) textarea::placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_formField__w6mH9:has(textarea) legend {\n height: 24px;\n position: absolute;\n left: 8px;\n transition: all 0.25s ease;\n}\n.formfield-module_formField__w6mH9:has([is=coles-solid-select]) {\n position: relative;\n height: 48px !important;\n padding: 0px !important;\n width: 100%;\n}\n.formfield-module_formField__w6mH9:has([is=coles-solid-select]) legend {\n height: 16px;\n max-height: 16px;\n transition: all 0.25s ease;\n top: calc(50% - 1em);\n z-index: 10000;\n}\n.formfield-module_formField__w6mH9:has([is=coles-solid-select]) [is=coles-solid-select] {\n position: absolute;\n left: 0px;\n right: 0px;\n padding: 0px !important;\n margin: 0px !important;\n height: 48px !important;\n border-radius: 4px;\n font-family: \"Roboto, sans-serif\";\n font-size: 16px;\n width: auto;\n min-width: 95%;\n}\n.formfield-module_formField__w6mH9:has([is=coles-solid-select]) [is=coles-solid-select]:nth-child(n) {\n border-radius: 4px;\n}\n.formfield-module_formField__w6mH9:has(input[type=text]) {\n height: 48px;\n position: relative;\n width: 100%;\n margin-top: 16px;\n margin-bottom: 16px;\n}\n.formfield-module_formField__w6mH9:has(input[type=text]) legend {\n position: absolute;\n height: 24px;\n left: 8px;\n transition: all 0.25s ease;\n}\n.formfield-module_formField__w6mH9:has(input[type=text]) input[type=text] {\n background-color: transparent !important;\n height: 24px;\n border-radius: 4px;\n margin: 8px 0px;\n font-family: \"Roboto, sans-serif\";\n font-size: 16px;\n width: 100%;\n min-width: 95%;\n}\n.formfield-module_formField__w6mH9:has(input[type=text]) input[type=text]::-moz-placeholder {\n opacity: 0;\n}\n.formfield-module_formField__w6mH9:has(input[type=text]) input[type=text]::placeholder {\n opacity: 0;\n}\n.formfield-module_formField__w6mH9:has(input[type=number]) {\n height: 48px;\n position: relative;\n width: 100%;\n margin-top: 16px;\n margin-bottom: 16px;\n}\n.formfield-module_formField__w6mH9:has(input[type=number]) legend {\n height: 24px;\n position: absolute;\n left: 8px;\n transition: all 0.25s ease;\n}\n.formfield-module_formField__w6mH9:has(input[type=number]) input[type=number] {\n background-color: transparent !important;\n color: var(--on-primary-color, #fff);\n height: 24px;\n border-radius: 4px;\n margin: 8px 0px;\n font-family: \"Roboto, sans-serif\";\n font-size: 16px;\n width: 100%;\n min-width: 95%;\n}\n.formfield-module_formField__w6mH9:has(input[type=number]) input[type=number]::-moz-placeholder {\n opacity: 0;\n}\n.formfield-module_formField__w6mH9:has(input[type=number]) input[type=number]::placeholder {\n opacity: 0;\n}\n@media screen and (max-width: 768px) {\n .formfield-module_formField__w6mH9 {\n max-width: 75%;\n }\n}\n\n.formfield-module_topMargin__dahW5 {\n margin-top: 12px;\n}\n\n.formfield-module_primary__7BYyQ:has(input[type=text]) input[type=text] {\n color: var(--on-container-color, #000);\n}\n.formfield-module_primary__7BYyQ:has(input[type=text]) input[type=text]::-moz-placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_primary__7BYyQ:has(input[type=text]) input[type=text]::placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_primary__7BYyQ:has(input[type=number]) input[type=number] {\n color: var(--on-container-color, #000);\n}\n.formfield-module_primary__7BYyQ:has(input[type=number]) input[type=number]::-moz-placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_primary__7BYyQ:has(input[type=number]) input[type=number]::placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_primary__7BYyQ:has([is=coles-solid-select]) [is=coles-solid-select] {\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n}\n.formfield-module_primary__7BYyQ:has(textarea) {\n width: 100%;\n height: auto;\n}\n.formfield-module_primary__7BYyQ:has(textarea) textarea {\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n}\n.formfield-module_primary__7BYyQ:has(textarea) textarea::-moz-placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_primary__7BYyQ:has(textarea) textarea::placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n\n.formfield-module_legendStyle__gnI49 {\n background-color: transparent;\n opacity: var(--text-emphasis-medium, 87%);\n width: 100%;\n transition: all 0.3s ease;\n}\n\n.formfield-module_checkboxPadding__DU1CG {\n padding: 0px;\n padding-bottom: 10px;\n padding-left: 10px;\n padding-right: 10px;\n}\n\n.formfield-module_errorContainer__HR4PL {\n position: relative;\n min-height: 2rem;\n}\n\n.formfield-module_error__wNBh2 {\n position: absolute;\n background: transparent;\n color: var(--error-color, #B00020);\n font-size: 10px;\n}";
4129
+ var css_248z$2 = ".formfield-module_formField__w6mH9:focus-within > legend, .formfield-module_has-focus__9ingx > legend {\n top: -8px !important;\n font-size: 0.75rem !important;\n}\n\n.formfield-module_formField__w6mH9 {\n position: relative;\n display: inline-block;\n border-radius: var(--border-radius-md);\n box-sizing: border-box;\n border: none;\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n margin-top: 0px !important;\n margin-bottom: 0px !important;\n}\n.formfield-module_formField__w6mH9 > legend {\n position: absolute;\n left: 12px;\n top: calc(50% - 0.5em);\n font-size: 1rem;\n transition: top 0.25s ease, font-size 0.25s ease;\n pointer-events: none;\n}\n.formfield-module_formField__w6mH9 input::-moz-placeholder, .formfield-module_formField__w6mH9 select::-moz-placeholder {\n opacity: 0 !important;\n -moz-transition: opacity 0.25s ease;\n transition: opacity 0.25s ease;\n}\n.formfield-module_formField__w6mH9 input::placeholder,\n.formfield-module_formField__w6mH9 select::placeholder {\n opacity: 0 !important;\n transition: opacity 0.25s ease;\n}\n.formfield-module_formField__w6mH9 label {\n position: relative;\n top: -0.5rem;\n padding-right: 10px;\n}\n.formfield-module_formField__w6mH9:has(textarea) {\n position: relative;\n margin: 8px;\n}\n.formfield-module_formField__w6mH9:has(textarea) textarea {\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n width: auto;\n min-width: 95%;\n font-family: \"Roboto, sans-serif\";\n font-size: 16px;\n padding-bottom: 8px;\n border: none;\n}\n.formfield-module_formField__w6mH9:has(textarea) textarea:focus {\n outline: none;\n}\n.formfield-module_formField__w6mH9:has(textarea) textarea::-moz-placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_formField__w6mH9:has(textarea) textarea::placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_formField__w6mH9:has(textarea) legend {\n height: 24px;\n position: absolute;\n left: 8px;\n transition: all 0.25s ease;\n}\n.formfield-module_formField__w6mH9:has([is=coles-solid-select]) {\n position: relative;\n height: 48px !important;\n padding: 0px !important;\n width: 100%;\n}\n.formfield-module_formField__w6mH9:has([is=coles-solid-select]) legend {\n height: 16px;\n max-height: 16px;\n transition: all 0.25s ease;\n top: calc(50% - 1em);\n z-index: 1;\n}\n.formfield-module_formField__w6mH9:has([is=coles-solid-select]) [is=coles-solid-select] {\n position: absolute;\n left: 0px;\n right: 0px;\n padding: 0px !important;\n margin: 0px !important;\n height: 48px !important;\n border-radius: 4px;\n font-family: \"Roboto, sans-serif\";\n font-size: 16px;\n width: auto;\n min-width: 95%;\n z-index: 0;\n}\n.formfield-module_formField__w6mH9:has([is=coles-solid-select]) [is=coles-solid-select]:nth-child(n) {\n border-radius: 4px;\n}\n.formfield-module_formField__w6mH9:has(input[type=text]) {\n height: 48px;\n position: relative;\n width: 100%;\n margin-top: 16px;\n margin-bottom: 16px;\n}\n.formfield-module_formField__w6mH9:has(input[type=text]) legend {\n position: absolute;\n height: 24px;\n left: 8px;\n transition: all 0.25s ease;\n}\n.formfield-module_formField__w6mH9:has(input[type=text]) input[type=text] {\n background-color: transparent !important;\n height: 24px;\n border-radius: 4px;\n margin: 8px 0px;\n font-family: \"Roboto, sans-serif\";\n font-size: 16px;\n width: 100%;\n min-width: 95%;\n}\n.formfield-module_formField__w6mH9:has(input[type=text]) input[type=text]::-moz-placeholder {\n opacity: 0;\n}\n.formfield-module_formField__w6mH9:has(input[type=text]) input[type=text]::placeholder {\n opacity: 0;\n}\n.formfield-module_formField__w6mH9:has(input[type=number]) {\n height: 48px;\n position: relative;\n width: 100%;\n margin-top: 16px;\n margin-bottom: 16px;\n}\n.formfield-module_formField__w6mH9:has(input[type=number]) legend {\n height: 24px;\n position: absolute;\n left: 8px;\n transition: all 0.25s ease;\n}\n.formfield-module_formField__w6mH9:has(input[type=number]) input[type=number] {\n background-color: transparent !important;\n color: var(--on-primary-color, #fff);\n height: 24px;\n border-radius: 4px;\n margin: 8px 0px;\n font-family: \"Roboto, sans-serif\";\n font-size: 16px;\n width: 100%;\n min-width: 95%;\n}\n.formfield-module_formField__w6mH9:has(input[type=number]) input[type=number]::-moz-placeholder {\n opacity: 0;\n}\n.formfield-module_formField__w6mH9:has(input[type=number]) input[type=number]::placeholder {\n opacity: 0;\n}\n@media screen and (max-width: 768px) {\n .formfield-module_formField__w6mH9 {\n max-width: 75%;\n }\n}\n\n.formfield-module_topMargin__dahW5 {\n margin-top: 12px;\n}\n\n.formfield-module_primary__7BYyQ:has(input[type=text]) input[type=text] {\n color: var(--on-container-color, #000);\n}\n.formfield-module_primary__7BYyQ:has(input[type=text]) input[type=text]::-moz-placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_primary__7BYyQ:has(input[type=text]) input[type=text]::placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_primary__7BYyQ:has(input[type=number]) input[type=number] {\n color: var(--on-container-color, #000);\n}\n.formfield-module_primary__7BYyQ:has(input[type=number]) input[type=number]::-moz-placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_primary__7BYyQ:has(input[type=number]) input[type=number]::placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_primary__7BYyQ:has([is=coles-solid-select]) [is=coles-solid-select] {\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n}\n.formfield-module_primary__7BYyQ:has(textarea) {\n width: 100%;\n height: auto;\n}\n.formfield-module_primary__7BYyQ:has(textarea) textarea {\n background-color: var(--container-color, #ffffff);\n color: var(--on-container-color, #000);\n}\n.formfield-module_primary__7BYyQ:has(textarea) textarea::-moz-placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n.formfield-module_primary__7BYyQ:has(textarea) textarea::placeholder {\n color: var(--on-container-color, #000);\n opacity: var(--text-emphasis-medium, 87%);\n}\n\n.formfield-module_legendStyle__gnI49 {\n background-color: transparent;\n opacity: var(--text-emphasis-medium, 87%);\n width: 100%;\n transition: all 0.3s ease;\n}\n\n.formfield-module_checkboxPadding__DU1CG {\n padding: 0px;\n padding-bottom: 10px;\n padding-left: 10px;\n padding-right: 10px;\n}\n\n.formfield-module_errorContainer__HR4PL {\n position: relative;\n min-height: 2rem;\n}\n\n.formfield-module_error__wNBh2 {\n position: absolute;\n background: transparent;\n color: var(--error-color, #B00020);\n font-size: 10px;\n}";
3694
4130
  var style = {"formField":"formfield-module_formField__w6mH9","has-focus":"formfield-module_has-focus__9ingx","primary":"formfield-module_primary__7BYyQ","legendStyle":"formfield-module_legendStyle__gnI49","errorContainer":"formfield-module_errorContainer__HR4PL","error":"formfield-module_error__wNBh2"};
3695
4131
  styleInject(css_248z$2);
3696
4132
 
@@ -3732,12 +4168,15 @@ const FormField2 = props => {
3732
4168
  };
3733
4169
  const shouldFloat = createMemo(() => {
3734
4170
  let currentVal;
3735
- // Prefer form context store value
3736
- if (hasValue(formContext?.data?.[local?.formName ?? ''])) {
3737
- currentVal = formContext?.data?.[local?.formName ?? ''];
3738
- }
3739
- // Fallback to local provider value (some components set this first)
3740
- if (hasValue(context?.getValue?.())) {
4171
+ const hasFormContext = !!local?.formName && !!formContext?.formGroup;
4172
+ // Prefer form context store value when available
4173
+ if (hasFormContext) {
4174
+ const formVal = formContext?.data?.[local?.formName ?? ''];
4175
+ if (hasValue(formVal)) {
4176
+ currentVal = formVal;
4177
+ }
4178
+ } else if (hasValue(context?.getValue?.())) {
4179
+ // Fallback to local provider value only when no form context
3741
4180
  currentVal = context?.getValue?.();
3742
4181
  }
3743
4182
  // Float when value present, focused, or control marked dirty (programmatic set)
@@ -3745,8 +4184,8 @@ const FormField2 = props => {
3745
4184
  const metaDirty = local?.formName ? !!formContext?.formGroup?.getMeta?.(local.formName)?.dirty : false;
3746
4185
  // Float when there is a value, or focused, or meta marked dirty (programmatic set),
3747
4186
  // or legacy input marked dirty-on-focus even if still empty (metaDirty && no value yet)
3748
- if (metaDirty && !hasValue(currentVal)) return true;
3749
- return hasValue(currentVal) || context?.getFocused?.() || isDirty();
4187
+ const hasAnyValue = hasValue(currentVal);
4188
+ return hasAnyValue || context?.getFocused?.() || metaDirty && hasAnyValue || isDirty() && hasAnyValue;
3750
4189
  });
3751
4190
  // Effect: if underlying meta resets to pristine and value cleared, ensure focused state cleared
3752
4191
  createEffect(() => {
@@ -3798,12 +4237,12 @@ const FormField2 = props => {
3798
4237
  const val = context?.getValue?.();
3799
4238
  context?.setTextInside(!hasValue(val));
3800
4239
  }
3801
- context?.setFocused(prev => {
3802
- if (prev) {
3803
- formContext?.formGroup?.validate?.(local?.formName ?? '');
3804
- }
3805
- return false;
3806
- });
4240
+ const metaDirty = local?.formName ? !!formContext?.formGroup?.getMeta?.(local.formName)?.dirty : false;
4241
+ const shouldValidate = !!context?.getFocused?.() || metaDirty;
4242
+ if (shouldValidate) {
4243
+ formContext?.formGroup?.validate?.(local?.formName ?? '');
4244
+ }
4245
+ context?.setFocused(false);
3807
4246
  });
3808
4247
  onMount(() => {
3809
4248
  if (context?.getValue !== undefined) {