@viax.io/uxm 4.39.0 → 4.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +33 -44
  4. package/dist/hooks/index.cjs.map +1 -1
  5. package/dist/hooks/index.d.ts +1 -1
  6. package/dist/hooks/index.js.map +1 -1
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.ts +3 -3
  9. package/dist/index.js.map +1 -1
  10. package/dist/previews/index.cjs.map +1 -1
  11. package/dist/previews/index.d.ts +2 -2
  12. package/dist/previews/index.js.map +1 -1
  13. package/dist/studio/index.cjs.map +1 -1
  14. package/dist/studio/index.d.ts +2 -2
  15. package/dist/studio/index.js.map +1 -1
  16. package/dist/studio/lib/registry/buttons.cjs +2 -2
  17. package/dist/studio/lib/registry/buttons.cjs.map +1 -1
  18. package/dist/studio/lib/registry/buttons.js +2 -2
  19. package/dist/studio/lib/registry/buttons.js.map +1 -1
  20. package/dist/studio/lib/registry/composite/sidebar-nav-trigger.cjs +1 -1
  21. package/dist/studio/lib/registry/composite/sidebar-nav-trigger.cjs.map +1 -1
  22. package/dist/studio/lib/registry/composite/sidebar-nav-trigger.js +1 -1
  23. package/dist/studio/lib/registry/composite/sidebar-nav-trigger.js.map +1 -1
  24. package/dist/studio/lib/registry/diagram.cjs +1 -1
  25. package/dist/studio/lib/registry/diagram.cjs.map +1 -1
  26. package/dist/studio/lib/registry/diagram.js +1 -1
  27. package/dist/studio/lib/registry/diagram.js.map +1 -1
  28. package/dist/studio/lib/registry/display.cjs +2 -2
  29. package/dist/studio/lib/registry/display.cjs.map +1 -1
  30. package/dist/studio/lib/registry/display.js +2 -2
  31. package/dist/studio/lib/registry/display.js.map +1 -1
  32. package/dist/studio/lib/registry/feedback.cjs +3 -3
  33. package/dist/studio/lib/registry/feedback.cjs.map +1 -1
  34. package/dist/studio/lib/registry/feedback.js +3 -3
  35. package/dist/studio/lib/registry/feedback.js.map +1 -1
  36. package/dist/studio/lib/registry/inputs/color-input.cjs +1 -1
  37. package/dist/studio/lib/registry/inputs/color-input.cjs.map +1 -1
  38. package/dist/studio/lib/registry/inputs/color-input.js +1 -1
  39. package/dist/studio/lib/registry/inputs/color-input.js.map +1 -1
  40. package/dist/studio/lib/registry/inputs/currency-input.cjs +1 -1
  41. package/dist/studio/lib/registry/inputs/currency-input.cjs.map +1 -1
  42. package/dist/studio/lib/registry/inputs/currency-input.js +1 -1
  43. package/dist/studio/lib/registry/inputs/currency-input.js.map +1 -1
  44. package/dist/studio/lib/registry/inputs/editable-cell.cjs +1 -1
  45. package/dist/studio/lib/registry/inputs/editable-cell.cjs.map +1 -1
  46. package/dist/studio/lib/registry/inputs/editable-cell.js +1 -1
  47. package/dist/studio/lib/registry/inputs/editable-cell.js.map +1 -1
  48. package/dist/studio/lib/registry/inputs/file-upload.cjs +1 -1
  49. package/dist/studio/lib/registry/inputs/file-upload.cjs.map +1 -1
  50. package/dist/studio/lib/registry/inputs/file-upload.js +1 -1
  51. package/dist/studio/lib/registry/inputs/file-upload.js.map +1 -1
  52. package/dist/studio/lib/registry/inputs/input-text.cjs +1 -1
  53. package/dist/studio/lib/registry/inputs/input-text.cjs.map +1 -1
  54. package/dist/studio/lib/registry/inputs/input-text.js +1 -1
  55. package/dist/studio/lib/registry/inputs/input-text.js.map +1 -1
  56. package/dist/studio/lib/registry/inputs/listbox.cjs +1 -1
  57. package/dist/studio/lib/registry/inputs/listbox.cjs.map +1 -1
  58. package/dist/studio/lib/registry/inputs/listbox.js +1 -1
  59. package/dist/studio/lib/registry/inputs/listbox.js.map +1 -1
  60. package/dist/studio/lib/registry/inputs/menu.cjs +1 -1
  61. package/dist/studio/lib/registry/inputs/menu.cjs.map +1 -1
  62. package/dist/studio/lib/registry/inputs/menu.js +1 -1
  63. package/dist/studio/lib/registry/inputs/menu.js.map +1 -1
  64. package/dist/studio/lib/registry/inputs/number-input.cjs +1 -1
  65. package/dist/studio/lib/registry/inputs/number-input.cjs.map +1 -1
  66. package/dist/studio/lib/registry/inputs/number-input.js +1 -1
  67. package/dist/studio/lib/registry/inputs/number-input.js.map +1 -1
  68. package/dist/studio/lib/registry/inputs/password-input.cjs +1 -1
  69. package/dist/studio/lib/registry/inputs/password-input.cjs.map +1 -1
  70. package/dist/studio/lib/registry/inputs/password-input.js +1 -1
  71. package/dist/studio/lib/registry/inputs/password-input.js.map +1 -1
  72. package/dist/studio/lib/registry/inputs/phone-input.cjs +1 -1
  73. package/dist/studio/lib/registry/inputs/phone-input.cjs.map +1 -1
  74. package/dist/studio/lib/registry/inputs/phone-input.js +1 -1
  75. package/dist/studio/lib/registry/inputs/phone-input.js.map +1 -1
  76. package/dist/studio/lib/registry/inputs/slider.cjs +1 -1
  77. package/dist/studio/lib/registry/inputs/slider.cjs.map +1 -1
  78. package/dist/studio/lib/registry/inputs/slider.js +1 -1
  79. package/dist/studio/lib/registry/inputs/slider.js.map +1 -1
  80. package/dist/studio/lib/registry/inputs/time-input.cjs +1 -1
  81. package/dist/studio/lib/registry/inputs/time-input.cjs.map +1 -1
  82. package/dist/studio/lib/registry/inputs/time-input.js +1 -1
  83. package/dist/studio/lib/registry/inputs/time-input.js.map +1 -1
  84. package/dist/studio/lib/types.cjs.map +1 -1
  85. package/dist/studio/persistence/generate-css.cjs.map +1 -1
  86. package/dist/studio/persistence/generate-css.js.map +1 -1
  87. package/dist/ui/editable-cell/editable-cell-date.cjs +226 -0
  88. package/dist/ui/editable-cell/editable-cell-date.cjs.map +1 -0
  89. package/dist/ui/editable-cell/editable-cell-date.d.ts +4 -0
  90. package/dist/ui/editable-cell/editable-cell-date.d.ts.map +1 -0
  91. package/dist/ui/editable-cell/editable-cell-date.js +202 -0
  92. package/dist/ui/editable-cell/editable-cell-date.js.map +1 -0
  93. package/dist/ui/editable-cell/editable-cell-select.cjs +297 -0
  94. package/dist/ui/editable-cell/editable-cell-select.cjs.map +1 -0
  95. package/dist/ui/editable-cell/editable-cell-select.d.ts +4 -0
  96. package/dist/ui/editable-cell/editable-cell-select.d.ts.map +1 -0
  97. package/dist/ui/editable-cell/editable-cell-select.js +273 -0
  98. package/dist/ui/editable-cell/editable-cell-select.js.map +1 -0
  99. package/dist/ui/editable-cell/editable-cell-text.cjs +175 -0
  100. package/dist/ui/editable-cell/editable-cell-text.cjs.map +1 -0
  101. package/dist/ui/editable-cell/editable-cell-text.d.ts +4 -0
  102. package/dist/ui/editable-cell/editable-cell-text.d.ts.map +1 -0
  103. package/dist/ui/editable-cell/editable-cell-text.js +151 -0
  104. package/dist/ui/editable-cell/editable-cell-text.js.map +1 -0
  105. package/dist/ui/editable-cell/editable-cell.cjs +27 -705
  106. package/dist/ui/editable-cell/editable-cell.cjs.map +1 -1
  107. package/dist/ui/editable-cell/editable-cell.d.ts +1 -1
  108. package/dist/ui/editable-cell/editable-cell.d.ts.map +1 -1
  109. package/dist/ui/editable-cell/editable-cell.js +28 -706
  110. package/dist/ui/editable-cell/editable-cell.js.map +1 -1
  111. package/dist/ui/editable-cell/use-editable-cell.cjs +284 -0
  112. package/dist/ui/editable-cell/use-editable-cell.cjs.map +1 -0
  113. package/dist/ui/editable-cell/use-editable-cell.d.ts +51 -0
  114. package/dist/ui/editable-cell/use-editable-cell.d.ts.map +1 -0
  115. package/dist/ui/editable-cell/use-editable-cell.js +260 -0
  116. package/dist/ui/editable-cell/use-editable-cell.js.map +1 -0
  117. package/dist/ui/page-shell/page-shell.cjs.map +1 -1
  118. package/dist/ui/page-shell/page-shell.d.ts +1 -1
  119. package/dist/ui/page-shell/page-shell.d.ts.map +1 -1
  120. package/dist/ui/page-shell/page-shell.js.map +1 -1
  121. package/dist/ui/styles.css +1 -1
  122. package/package.json +5 -5
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/ui/editable-cell/editable-cell-date.tsx"],"sourcesContent":["import { cn } from '@/helpers';\n\nimport { Banner } from '../banner';\nimport { Calendar, type CalendarValue } from '../calendar';\nimport { FORMAT_SPEC, maskDate } from '../date-input';\nimport { HoverTooltip } from '../hover-tooltip';\nimport { Icon } from '../icon';\nimport { Popover } from '../popover';\n\nimport type { EditableCellViewProps } from './use-editable-cell';\n\n/** `type=\"date\"` — click-to-edit with a masked input plus a calendar popover. */\nexport function EditableCellDateView({ props, cell }: EditableCellViewProps) {\n const {\n value,\n format,\n disabled,\n placeholder,\n className,\n style,\n 'aria-label': ariaLabel,\n type,\n dateFormat,\n clearable,\n align,\n size,\n clearDateLabel,\n openCalendarLabel,\n calendarDialogLabel,\n addDateLabel,\n } = props;\n const {\n setIsEditing,\n draft,\n setDraft,\n submitting,\n error,\n setError,\n open,\n setOpen,\n inputRef,\n wrapRef,\n parsedValue,\n displayFormatted,\n handleCommit,\n handlePick,\n handleClearDraft,\n handleKeyDown,\n editing,\n dateHint,\n isEmpty,\n display,\n titleText,\n shownError,\n } = cell;\n\n // Date type — click-to-edit like text/number, but the editing surface is a\n // DateInput-style masked field: type the date OR pick it from the calendar\n // that opens on focus. Committed values are ISO; the input shows the mask.\n if (type === 'date') {\n // `parsedValue` (memoized above) already parses ISO-first with a mask\n // fallback, so the calendar highlights the right day for every `dateFormat`.\n const calendarValue: CalendarValue = { start: parsedValue, end: parsedValue };\n const spec = FORMAT_SPEC[dateFormat];\n\n if (!editing) {\n const displayNode = isEmpty\n // Fall back to the format hint (MM/DD/YYYY etc.) so an empty date cell\n // shows the mask as a placeholder — same as the shared `display` and\n // the edit-mode input, rather than rendering blank.\n ? placeholder ?? dateHint\n : format\n ? format(value)\n : displayFormatted || value;\n\n // Single button root — same shape as the text/number display so the\n // value's left edge and padding match the editing input exactly (no\n // horizontal jump on enter-edit). A wrapper + inner trigger would\n // double the padding; the display has no popover to anchor, so the\n // wrapper span is only needed in edit mode (for the calendar/error\n // popovers).\n return (\n <button\n type=\"button\"\n className={cn(\n 'uxm-editable-cell',\n `uxm-editable-cell--${size}`,\n `uxm-editable-cell--align-${align}`,\n `uxm-editable-cell--type-date`,\n disabled && 'uxm-editable-cell--disabled',\n isEmpty && 'uxm-editable-cell--empty',\n className,\n )}\n style={style}\n onClick={() => {\n if (disabled) return;\n // Enter edit AND open the calendar in one deterministic step —\n // mirrors DateInput's \"focus reveals the calendar\". Opening here\n // (rather than on the input's onFocus) avoids the focus-after-\n // remount race: the display button and editing input are\n // different elements, so the auto-focus that mounts the input\n // doesn't reliably deliver a focus event the calendar can hook.\n setIsEditing(true);\n setOpen(true);\n }}\n disabled={disabled}\n // Empty cell has no value to edit — \"Add date\" reads better than the\n // trailing-space \"Edit date \" and signals the fill affordance.\n aria-label={ariaLabel ?? (isEmpty ? addDateLabel : `Edit date ${displayFormatted || String(value)}`)}\n >\n <HoverTooltip content={titleText} disabled={disabled}>\n <span className=\"uxm-editable-cell__value\">{displayNode}</span>\n </HoverTooltip>\n {!disabled && (\n <span className=\"uxm-editable-cell__pencil\" aria-hidden=\"true\">\n <Icon glyph=\"calendar\" size={14} />\n </span>\n )}\n </button>\n );\n }\n\n // Date editing — DateInput-style masked input plus a calendar popover.\n return (\n <span\n ref={wrapRef}\n className={cn(\n 'uxm-editable-cell uxm-editable-cell--editing',\n `uxm-editable-cell--${size}`,\n `uxm-editable-cell--align-${align}`,\n `uxm-editable-cell--type-date`,\n clearable && 'uxm-editable-cell--clearable',\n shownError?.severity === 'error' && 'uxm-editable-cell--error',\n shownError?.severity === 'warning' && 'uxm-editable-cell--warning',\n className,\n )}\n style={style}\n >\n <span className=\"uxm-editable-cell__ghost\" aria-hidden=\"true\">\n {display}\n </span>\n <span className=\"uxm-editable-cell__ghost\" aria-hidden=\"true\">\n {draft || spec.placeholder}\n </span>\n <input\n ref={inputRef}\n type=\"text\"\n inputMode=\"numeric\"\n className=\"uxm-editable-cell__input\"\n value={draft}\n placeholder={spec.placeholder}\n onChange={(e) => {\n setDraft(maskDate(e.target.value, dateFormat));\n if (error) setError(null);\n }}\n onBlur={() => {\n if (!submitting) handleCommit();\n }}\n onKeyDown={handleKeyDown}\n disabled={submitting}\n aria-invalid={Boolean(shownError)}\n aria-describedby={shownError ? 'uxm-editable-cell__error' : undefined}\n />\n {/* ✕ sits inboard of the calendar toggle (mirrors DateInput's layout);\n hidden while the draft is empty — the reserved gutter stays, so\n typing never shifts the text. */}\n {clearable && !submitting && draft !== '' && (\n <button\n type=\"button\"\n className=\"uxm-editable-cell__clear\"\n // Out of the tab order (the in-field-clear convention). Tab must\n // keep moving to the next real control: the blur it fires commits\n // and leaves edit mode, which unmounts this button mid-focus-shift\n // and would drop focus to <body>. Pointer-only; select-all +\n // Delete is the keyboard path to the same result.\n tabIndex={-1}\n onMouseDown={(e) => e.preventDefault()}\n onClick={handleClearDraft}\n aria-label={clearDateLabel}\n >\n <Icon glyph=\"close\" size={12} />\n </button>\n )}\n <button\n type=\"button\"\n className=\"uxm-editable-cell__date-icon\"\n // Out of the tab order for the same reason as the ✕ above — Tab's\n // blur commits and unmounts this button. Keyboard users never need\n // it: entering edit mode on a date cell already opens the calendar.\n tabIndex={-1}\n // preventDefault keeps focus on the input — toggling the calendar\n // must not blur the field (a blur commits the in-flight draft).\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n if (submitting) return;\n // Clear any shown error as we open, so the calendar and the error\n // banner (both anchored here) are mutually exclusive — otherwise a\n // later `setError(null)` from typing would un-hide and reopen the\n // calendar the user had dismissed.\n setError(null);\n setOpen((o) => !o);\n }}\n disabled={submitting}\n aria-label={openCalendarLabel}\n // Match the popover's effective visibility (hidden while an error\n // shows) rather than raw `open`, so the two never disagree.\n aria-expanded={open && !shownError}\n >\n <Icon glyph=\"calendar\" size={14} />\n </button>\n <Popover\n open={open && !shownError}\n onOpenChange={setOpen}\n anchor={wrapRef}\n placement=\"bottom-start\"\n closeOnEscape\n closeOnOutsideClick\n restoreFocus={false}\n role=\"dialog\"\n // A `role=\"dialog\"` needs an accessible name. Non-modal by design\n // (no `aria-modal`): focus deliberately stays in the typed input\n // — `restoreFocus={false}` and the mousedown-preventDefault above\n // keep the field focused so the calendar augments typing rather\n // than trapping focus like a true modal.\n aria-label={calendarDialogLabel}\n >\n {/* Swallow mousedown so a calendar click never blurs the input:\n the pick commits explicitly via handlePick, and a blur-commit of\n the typed draft would race it. Purely focus management — the\n wrapper carries no semantics, so it stays a plain element. */}\n {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions -- focus-retention only; the interactive controls are the Calendar's own buttons */}\n <div onMouseDown={(e) => e.preventDefault()}>\n <Calendar value={calendarValue} onChange={handlePick} />\n </div>\n </Popover>\n <Popover\n open={Boolean(shownError)}\n onOpenChange={(next) => {\n if (!next) setError(null);\n }}\n anchor={wrapRef}\n placement=\"bottom-start\"\n closeOnEscape={false}\n closeOnOutsideClick={false}\n restoreFocus={false}\n role=\"presentation\"\n >\n {shownError && (\n <Banner\n variant={shownError.severity}\n id=\"uxm-editable-cell__error\"\n className=\"uxm-editable-cell__error-banner\"\n >\n {shownError.message}\n </Banner>\n )}\n </Popover>\n </span>\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAkFQ;AAlFR,qBAAmB;AAEnB,oBAAuB;AACvB,sBAA6C;AAC7C,wBAAsC;AACtC,2BAA6B;AAC7B,kBAAqB;AACrB,qBAAwB;AAKjB,SAAS,qBAAqB,EAAE,OAAO,KAAK,GAA0B;AAC3E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAKJ,MAAI,SAAS,QAAQ;AAGnB,UAAM,gBAA+B,EAAE,OAAO,aAAa,KAAK,YAAY;AAC5E,UAAM,OAAO,8BAAY,UAAU;AAEnC,QAAI,CAAC,SAAS;AACZ,YAAM,cAAc,UAIhB,eAAe,WACf,SACE,OAAO,KAAK,IACZ,oBAAoB;AAQ1B,aACE;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,eAAW;AAAA,YACT;AAAA,YACA,sBAAsB,IAAI;AAAA,YAC1B,4BAA4B,KAAK;AAAA,YACjC;AAAA,YACA,YAAY;AAAA,YACZ,WAAW;AAAA,YACX;AAAA,UACF;AAAA,UACA;AAAA,UACA,SAAS,MAAM;AACb,gBAAI,SAAU;AAOd,yBAAa,IAAI;AACjB,oBAAQ,IAAI;AAAA,UACd;AAAA,UACA;AAAA,UAGA,cAAY,cAAc,UAAU,eAAe,aAAa,oBAAoB,OAAO,KAAK,CAAC;AAAA,UAEjG;AAAA,wDAAC,qCAAa,SAAS,WAAW,UAChC,sDAAC,UAAK,WAAU,4BAA4B,uBAAY,GAC1D;AAAA,YACC,CAAC,YACA,4CAAC,UAAK,WAAU,6BAA4B,eAAY,QACtD,sDAAC,oBAAK,OAAM,YAAW,MAAM,IAAI,GACnC;AAAA;AAAA;AAAA,MAEJ;AAAA,IAEJ;AAGA,WACE;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,eAAW;AAAA,UACT;AAAA,UACA,sBAAsB,IAAI;AAAA,UAC1B,4BAA4B,KAAK;AAAA,UACjC;AAAA,UACA,aAAa;AAAA,UACb,YAAY,aAAa,WAAW;AAAA,UACpC,YAAY,aAAa,aAAa;AAAA,UACtC;AAAA,QACF;AAAA,QACA;AAAA,QAEA;AAAA,sDAAC,UAAK,WAAU,4BAA2B,eAAY,QACpD,mBACH;AAAA,UACA,4CAAC,UAAK,WAAU,4BAA2B,eAAY,QACpD,mBAAS,KAAK,aACjB;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,MAAK;AAAA,cACL,WAAU;AAAA,cACV,WAAU;AAAA,cACV,OAAO;AAAA,cACP,aAAa,KAAK;AAAA,cAClB,UAAU,CAAC,MAAM;AACf,6BAAS,4BAAS,EAAE,OAAO,OAAO,UAAU,CAAC;AAC7C,oBAAI,MAAO,UAAS,IAAI;AAAA,cAC1B;AAAA,cACA,QAAQ,MAAM;AACZ,oBAAI,CAAC,WAAY,cAAa;AAAA,cAChC;AAAA,cACA,WAAW;AAAA,cACX,UAAU;AAAA,cACV,gBAAc,QAAQ,UAAU;AAAA,cAChC,oBAAkB,aAAa,6BAA6B;AAAA;AAAA,UAC9D;AAAA,UAIC,aAAa,CAAC,cAAc,UAAU,MACrC;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,cAMV,UAAU;AAAA,cACV,aAAa,CAAC,MAAM,EAAE,eAAe;AAAA,cACrC,SAAS;AAAA,cACT,cAAY;AAAA,cAEZ,sDAAC,oBAAK,OAAM,SAAQ,MAAM,IAAI;AAAA;AAAA,UAChC;AAAA,UAEF;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,cAIV,UAAU;AAAA,cAGV,aAAa,CAAC,MAAM,EAAE,eAAe;AAAA,cACrC,SAAS,MAAM;AACb,oBAAI,WAAY;AAKhB,yBAAS,IAAI;AACb,wBAAQ,CAAC,MAAM,CAAC,CAAC;AAAA,cACnB;AAAA,cACA,UAAU;AAAA,cACV,cAAY;AAAA,cAGZ,iBAAe,QAAQ,CAAC;AAAA,cAExB,sDAAC,oBAAK,OAAM,YAAW,MAAM,IAAI;AAAA;AAAA,UACnC;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAM,QAAQ,CAAC;AAAA,cACf,cAAc;AAAA,cACd,QAAQ;AAAA,cACR,WAAU;AAAA,cACV,eAAa;AAAA,cACb,qBAAmB;AAAA,cACnB,cAAc;AAAA,cACd,MAAK;AAAA,cAML,cAAY;AAAA,cAOZ,sDAAC,SAAI,aAAa,CAAC,MAAM,EAAE,eAAe,GACxC,sDAAC,4BAAS,OAAO,eAAe,UAAU,YAAY,GACxD;AAAA;AAAA,UACF;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAM,QAAQ,UAAU;AAAA,cACxB,cAAc,CAAC,SAAS;AACtB,oBAAI,CAAC,KAAM,UAAS,IAAI;AAAA,cAC1B;AAAA,cACA,QAAQ;AAAA,cACR,WAAU;AAAA,cACV,eAAe;AAAA,cACf,qBAAqB;AAAA,cACrB,cAAc;AAAA,cACd,MAAK;AAAA,cAEJ,wBACC;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAS,WAAW;AAAA,kBACpB,IAAG;AAAA,kBACH,WAAU;AAAA,kBAET,qBAAW;AAAA;AAAA,cACd;AAAA;AAAA,UAEJ;AAAA;AAAA;AAAA,IACF;AAAA,EAEJ;AACF;","names":[]}
@@ -0,0 +1,4 @@
1
+ import type { EditableCellViewProps } from './use-editable-cell.js';
2
+ /** `type="date"` — click-to-edit with a masked input plus a calendar popover. */
3
+ export declare function EditableCellDateView({ props, cell }: EditableCellViewProps): import("react").JSX.Element | undefined;
4
+ //# sourceMappingURL=editable-cell-date.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editable-cell-date.d.ts","sourceRoot":"","sources":["../../../src/ui/editable-cell/editable-cell-date.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEjE,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,qBAAqB,2CAwP1E"}
@@ -0,0 +1,202 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../../helpers/index.js";
3
+ import { Banner } from "../banner/index.js";
4
+ import { Calendar } from "../calendar/index.js";
5
+ import { FORMAT_SPEC, maskDate } from "../date-input/index.js";
6
+ import { HoverTooltip } from "../hover-tooltip/index.js";
7
+ import { Icon } from "../icon/index.js";
8
+ import { Popover } from "../popover/index.js";
9
+ function EditableCellDateView({ props, cell }) {
10
+ const {
11
+ value,
12
+ format,
13
+ disabled,
14
+ placeholder,
15
+ className,
16
+ style,
17
+ "aria-label": ariaLabel,
18
+ type,
19
+ dateFormat,
20
+ clearable,
21
+ align,
22
+ size,
23
+ clearDateLabel,
24
+ openCalendarLabel,
25
+ calendarDialogLabel,
26
+ addDateLabel
27
+ } = props;
28
+ const {
29
+ setIsEditing,
30
+ draft,
31
+ setDraft,
32
+ submitting,
33
+ error,
34
+ setError,
35
+ open,
36
+ setOpen,
37
+ inputRef,
38
+ wrapRef,
39
+ parsedValue,
40
+ displayFormatted,
41
+ handleCommit,
42
+ handlePick,
43
+ handleClearDraft,
44
+ handleKeyDown,
45
+ editing,
46
+ dateHint,
47
+ isEmpty,
48
+ display,
49
+ titleText,
50
+ shownError
51
+ } = cell;
52
+ if (type === "date") {
53
+ const calendarValue = { start: parsedValue, end: parsedValue };
54
+ const spec = FORMAT_SPEC[dateFormat];
55
+ if (!editing) {
56
+ const displayNode = isEmpty ? placeholder ?? dateHint : format ? format(value) : displayFormatted || value;
57
+ return /* @__PURE__ */ jsxs(
58
+ "button",
59
+ {
60
+ type: "button",
61
+ className: cn(
62
+ "uxm-editable-cell",
63
+ `uxm-editable-cell--${size}`,
64
+ `uxm-editable-cell--align-${align}`,
65
+ `uxm-editable-cell--type-date`,
66
+ disabled && "uxm-editable-cell--disabled",
67
+ isEmpty && "uxm-editable-cell--empty",
68
+ className
69
+ ),
70
+ style,
71
+ onClick: () => {
72
+ if (disabled) return;
73
+ setIsEditing(true);
74
+ setOpen(true);
75
+ },
76
+ disabled,
77
+ "aria-label": ariaLabel ?? (isEmpty ? addDateLabel : `Edit date ${displayFormatted || String(value)}`),
78
+ children: [
79
+ /* @__PURE__ */ jsx(HoverTooltip, { content: titleText, disabled, children: /* @__PURE__ */ jsx("span", { className: "uxm-editable-cell__value", children: displayNode }) }),
80
+ !disabled && /* @__PURE__ */ jsx("span", { className: "uxm-editable-cell__pencil", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Icon, { glyph: "calendar", size: 14 }) })
81
+ ]
82
+ }
83
+ );
84
+ }
85
+ return /* @__PURE__ */ jsxs(
86
+ "span",
87
+ {
88
+ ref: wrapRef,
89
+ className: cn(
90
+ "uxm-editable-cell uxm-editable-cell--editing",
91
+ `uxm-editable-cell--${size}`,
92
+ `uxm-editable-cell--align-${align}`,
93
+ `uxm-editable-cell--type-date`,
94
+ clearable && "uxm-editable-cell--clearable",
95
+ shownError?.severity === "error" && "uxm-editable-cell--error",
96
+ shownError?.severity === "warning" && "uxm-editable-cell--warning",
97
+ className
98
+ ),
99
+ style,
100
+ children: [
101
+ /* @__PURE__ */ jsx("span", { className: "uxm-editable-cell__ghost", "aria-hidden": "true", children: display }),
102
+ /* @__PURE__ */ jsx("span", { className: "uxm-editable-cell__ghost", "aria-hidden": "true", children: draft || spec.placeholder }),
103
+ /* @__PURE__ */ jsx(
104
+ "input",
105
+ {
106
+ ref: inputRef,
107
+ type: "text",
108
+ inputMode: "numeric",
109
+ className: "uxm-editable-cell__input",
110
+ value: draft,
111
+ placeholder: spec.placeholder,
112
+ onChange: (e) => {
113
+ setDraft(maskDate(e.target.value, dateFormat));
114
+ if (error) setError(null);
115
+ },
116
+ onBlur: () => {
117
+ if (!submitting) handleCommit();
118
+ },
119
+ onKeyDown: handleKeyDown,
120
+ disabled: submitting,
121
+ "aria-invalid": Boolean(shownError),
122
+ "aria-describedby": shownError ? "uxm-editable-cell__error" : void 0
123
+ }
124
+ ),
125
+ clearable && !submitting && draft !== "" && /* @__PURE__ */ jsx(
126
+ "button",
127
+ {
128
+ type: "button",
129
+ className: "uxm-editable-cell__clear",
130
+ tabIndex: -1,
131
+ onMouseDown: (e) => e.preventDefault(),
132
+ onClick: handleClearDraft,
133
+ "aria-label": clearDateLabel,
134
+ children: /* @__PURE__ */ jsx(Icon, { glyph: "close", size: 12 })
135
+ }
136
+ ),
137
+ /* @__PURE__ */ jsx(
138
+ "button",
139
+ {
140
+ type: "button",
141
+ className: "uxm-editable-cell__date-icon",
142
+ tabIndex: -1,
143
+ onMouseDown: (e) => e.preventDefault(),
144
+ onClick: () => {
145
+ if (submitting) return;
146
+ setError(null);
147
+ setOpen((o) => !o);
148
+ },
149
+ disabled: submitting,
150
+ "aria-label": openCalendarLabel,
151
+ "aria-expanded": open && !shownError,
152
+ children: /* @__PURE__ */ jsx(Icon, { glyph: "calendar", size: 14 })
153
+ }
154
+ ),
155
+ /* @__PURE__ */ jsx(
156
+ Popover,
157
+ {
158
+ open: open && !shownError,
159
+ onOpenChange: setOpen,
160
+ anchor: wrapRef,
161
+ placement: "bottom-start",
162
+ closeOnEscape: true,
163
+ closeOnOutsideClick: true,
164
+ restoreFocus: false,
165
+ role: "dialog",
166
+ "aria-label": calendarDialogLabel,
167
+ children: /* @__PURE__ */ jsx("div", { onMouseDown: (e) => e.preventDefault(), children: /* @__PURE__ */ jsx(Calendar, { value: calendarValue, onChange: handlePick }) })
168
+ }
169
+ ),
170
+ /* @__PURE__ */ jsx(
171
+ Popover,
172
+ {
173
+ open: Boolean(shownError),
174
+ onOpenChange: (next) => {
175
+ if (!next) setError(null);
176
+ },
177
+ anchor: wrapRef,
178
+ placement: "bottom-start",
179
+ closeOnEscape: false,
180
+ closeOnOutsideClick: false,
181
+ restoreFocus: false,
182
+ role: "presentation",
183
+ children: shownError && /* @__PURE__ */ jsx(
184
+ Banner,
185
+ {
186
+ variant: shownError.severity,
187
+ id: "uxm-editable-cell__error",
188
+ className: "uxm-editable-cell__error-banner",
189
+ children: shownError.message
190
+ }
191
+ )
192
+ }
193
+ )
194
+ ]
195
+ }
196
+ );
197
+ }
198
+ }
199
+ export {
200
+ EditableCellDateView
201
+ };
202
+ //# sourceMappingURL=editable-cell-date.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/ui/editable-cell/editable-cell-date.tsx"],"sourcesContent":["import { cn } from '@/helpers';\n\nimport { Banner } from '../banner';\nimport { Calendar, type CalendarValue } from '../calendar';\nimport { FORMAT_SPEC, maskDate } from '../date-input';\nimport { HoverTooltip } from '../hover-tooltip';\nimport { Icon } from '../icon';\nimport { Popover } from '../popover';\n\nimport type { EditableCellViewProps } from './use-editable-cell';\n\n/** `type=\"date\"` — click-to-edit with a masked input plus a calendar popover. */\nexport function EditableCellDateView({ props, cell }: EditableCellViewProps) {\n const {\n value,\n format,\n disabled,\n placeholder,\n className,\n style,\n 'aria-label': ariaLabel,\n type,\n dateFormat,\n clearable,\n align,\n size,\n clearDateLabel,\n openCalendarLabel,\n calendarDialogLabel,\n addDateLabel,\n } = props;\n const {\n setIsEditing,\n draft,\n setDraft,\n submitting,\n error,\n setError,\n open,\n setOpen,\n inputRef,\n wrapRef,\n parsedValue,\n displayFormatted,\n handleCommit,\n handlePick,\n handleClearDraft,\n handleKeyDown,\n editing,\n dateHint,\n isEmpty,\n display,\n titleText,\n shownError,\n } = cell;\n\n // Date type — click-to-edit like text/number, but the editing surface is a\n // DateInput-style masked field: type the date OR pick it from the calendar\n // that opens on focus. Committed values are ISO; the input shows the mask.\n if (type === 'date') {\n // `parsedValue` (memoized above) already parses ISO-first with a mask\n // fallback, so the calendar highlights the right day for every `dateFormat`.\n const calendarValue: CalendarValue = { start: parsedValue, end: parsedValue };\n const spec = FORMAT_SPEC[dateFormat];\n\n if (!editing) {\n const displayNode = isEmpty\n // Fall back to the format hint (MM/DD/YYYY etc.) so an empty date cell\n // shows the mask as a placeholder — same as the shared `display` and\n // the edit-mode input, rather than rendering blank.\n ? placeholder ?? dateHint\n : format\n ? format(value)\n : displayFormatted || value;\n\n // Single button root — same shape as the text/number display so the\n // value's left edge and padding match the editing input exactly (no\n // horizontal jump on enter-edit). A wrapper + inner trigger would\n // double the padding; the display has no popover to anchor, so the\n // wrapper span is only needed in edit mode (for the calendar/error\n // popovers).\n return (\n <button\n type=\"button\"\n className={cn(\n 'uxm-editable-cell',\n `uxm-editable-cell--${size}`,\n `uxm-editable-cell--align-${align}`,\n `uxm-editable-cell--type-date`,\n disabled && 'uxm-editable-cell--disabled',\n isEmpty && 'uxm-editable-cell--empty',\n className,\n )}\n style={style}\n onClick={() => {\n if (disabled) return;\n // Enter edit AND open the calendar in one deterministic step —\n // mirrors DateInput's \"focus reveals the calendar\". Opening here\n // (rather than on the input's onFocus) avoids the focus-after-\n // remount race: the display button and editing input are\n // different elements, so the auto-focus that mounts the input\n // doesn't reliably deliver a focus event the calendar can hook.\n setIsEditing(true);\n setOpen(true);\n }}\n disabled={disabled}\n // Empty cell has no value to edit — \"Add date\" reads better than the\n // trailing-space \"Edit date \" and signals the fill affordance.\n aria-label={ariaLabel ?? (isEmpty ? addDateLabel : `Edit date ${displayFormatted || String(value)}`)}\n >\n <HoverTooltip content={titleText} disabled={disabled}>\n <span className=\"uxm-editable-cell__value\">{displayNode}</span>\n </HoverTooltip>\n {!disabled && (\n <span className=\"uxm-editable-cell__pencil\" aria-hidden=\"true\">\n <Icon glyph=\"calendar\" size={14} />\n </span>\n )}\n </button>\n );\n }\n\n // Date editing — DateInput-style masked input plus a calendar popover.\n return (\n <span\n ref={wrapRef}\n className={cn(\n 'uxm-editable-cell uxm-editable-cell--editing',\n `uxm-editable-cell--${size}`,\n `uxm-editable-cell--align-${align}`,\n `uxm-editable-cell--type-date`,\n clearable && 'uxm-editable-cell--clearable',\n shownError?.severity === 'error' && 'uxm-editable-cell--error',\n shownError?.severity === 'warning' && 'uxm-editable-cell--warning',\n className,\n )}\n style={style}\n >\n <span className=\"uxm-editable-cell__ghost\" aria-hidden=\"true\">\n {display}\n </span>\n <span className=\"uxm-editable-cell__ghost\" aria-hidden=\"true\">\n {draft || spec.placeholder}\n </span>\n <input\n ref={inputRef}\n type=\"text\"\n inputMode=\"numeric\"\n className=\"uxm-editable-cell__input\"\n value={draft}\n placeholder={spec.placeholder}\n onChange={(e) => {\n setDraft(maskDate(e.target.value, dateFormat));\n if (error) setError(null);\n }}\n onBlur={() => {\n if (!submitting) handleCommit();\n }}\n onKeyDown={handleKeyDown}\n disabled={submitting}\n aria-invalid={Boolean(shownError)}\n aria-describedby={shownError ? 'uxm-editable-cell__error' : undefined}\n />\n {/* ✕ sits inboard of the calendar toggle (mirrors DateInput's layout);\n hidden while the draft is empty — the reserved gutter stays, so\n typing never shifts the text. */}\n {clearable && !submitting && draft !== '' && (\n <button\n type=\"button\"\n className=\"uxm-editable-cell__clear\"\n // Out of the tab order (the in-field-clear convention). Tab must\n // keep moving to the next real control: the blur it fires commits\n // and leaves edit mode, which unmounts this button mid-focus-shift\n // and would drop focus to <body>. Pointer-only; select-all +\n // Delete is the keyboard path to the same result.\n tabIndex={-1}\n onMouseDown={(e) => e.preventDefault()}\n onClick={handleClearDraft}\n aria-label={clearDateLabel}\n >\n <Icon glyph=\"close\" size={12} />\n </button>\n )}\n <button\n type=\"button\"\n className=\"uxm-editable-cell__date-icon\"\n // Out of the tab order for the same reason as the ✕ above — Tab's\n // blur commits and unmounts this button. Keyboard users never need\n // it: entering edit mode on a date cell already opens the calendar.\n tabIndex={-1}\n // preventDefault keeps focus on the input — toggling the calendar\n // must not blur the field (a blur commits the in-flight draft).\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n if (submitting) return;\n // Clear any shown error as we open, so the calendar and the error\n // banner (both anchored here) are mutually exclusive — otherwise a\n // later `setError(null)` from typing would un-hide and reopen the\n // calendar the user had dismissed.\n setError(null);\n setOpen((o) => !o);\n }}\n disabled={submitting}\n aria-label={openCalendarLabel}\n // Match the popover's effective visibility (hidden while an error\n // shows) rather than raw `open`, so the two never disagree.\n aria-expanded={open && !shownError}\n >\n <Icon glyph=\"calendar\" size={14} />\n </button>\n <Popover\n open={open && !shownError}\n onOpenChange={setOpen}\n anchor={wrapRef}\n placement=\"bottom-start\"\n closeOnEscape\n closeOnOutsideClick\n restoreFocus={false}\n role=\"dialog\"\n // A `role=\"dialog\"` needs an accessible name. Non-modal by design\n // (no `aria-modal`): focus deliberately stays in the typed input\n // — `restoreFocus={false}` and the mousedown-preventDefault above\n // keep the field focused so the calendar augments typing rather\n // than trapping focus like a true modal.\n aria-label={calendarDialogLabel}\n >\n {/* Swallow mousedown so a calendar click never blurs the input:\n the pick commits explicitly via handlePick, and a blur-commit of\n the typed draft would race it. Purely focus management — the\n wrapper carries no semantics, so it stays a plain element. */}\n {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions -- focus-retention only; the interactive controls are the Calendar's own buttons */}\n <div onMouseDown={(e) => e.preventDefault()}>\n <Calendar value={calendarValue} onChange={handlePick} />\n </div>\n </Popover>\n <Popover\n open={Boolean(shownError)}\n onOpenChange={(next) => {\n if (!next) setError(null);\n }}\n anchor={wrapRef}\n placement=\"bottom-start\"\n closeOnEscape={false}\n closeOnOutsideClick={false}\n restoreFocus={false}\n role=\"presentation\"\n >\n {shownError && (\n <Banner\n variant={shownError.severity}\n id=\"uxm-editable-cell__error\"\n className=\"uxm-editable-cell__error-banner\"\n >\n {shownError.message}\n </Banner>\n )}\n </Popover>\n </span>\n );\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,297 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var editable_cell_select_exports = {};
20
+ __export(editable_cell_select_exports, {
21
+ EditableCellSelectView: () => EditableCellSelectView
22
+ });
23
+ module.exports = __toCommonJS(editable_cell_select_exports);
24
+ var import_jsx_runtime = require("react/jsx-runtime");
25
+ var import_helpers = require("../../helpers/index.cjs");
26
+ var import_banner = require("../banner/index.cjs");
27
+ var import_button = require("../button/index.cjs");
28
+ var import_hover_tooltip = require("../hover-tooltip/index.cjs");
29
+ var import_icon = require("../icon/index.cjs");
30
+ var import_listbox = require("../listbox/index.cjs");
31
+ var import_popover = require("../popover/index.cjs");
32
+ function EditableCellSelectView({ props, cell }) {
33
+ const {
34
+ value,
35
+ options,
36
+ requiredMessage,
37
+ disabled,
38
+ className,
39
+ style,
40
+ "aria-label": ariaLabel,
41
+ type,
42
+ searchable,
43
+ clearable,
44
+ align,
45
+ size,
46
+ required,
47
+ clearSelectionLabel
48
+ } = props;
49
+ const {
50
+ submitting,
51
+ setError,
52
+ open,
53
+ setOpen,
54
+ wrapRef,
55
+ commitValue,
56
+ isEmpty,
57
+ display,
58
+ titleText,
59
+ shownError
60
+ } = cell;
61
+ if (type === "select" || type === "multiselect") {
62
+ const optionItems = options ?? [];
63
+ const getKey = (o) => o.value;
64
+ const getLabel = (o) => o.label;
65
+ if (type === "select") {
66
+ const selectedItem = Array.isArray(value) ? null : optionItems.find((o) => o.value === String(value ?? "")) ?? null;
67
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
68
+ "span",
69
+ {
70
+ ref: wrapRef,
71
+ className: (0, import_helpers.cn)(
72
+ "uxm-editable-cell",
73
+ `uxm-editable-cell--${size}`,
74
+ `uxm-editable-cell--align-${align}`,
75
+ `uxm-editable-cell--type-${type}`,
76
+ clearable && "uxm-editable-cell--clearable",
77
+ disabled && "uxm-editable-cell--disabled",
78
+ isEmpty && "uxm-editable-cell--empty",
79
+ open && "uxm-editable-cell--open",
80
+ className
81
+ ),
82
+ style,
83
+ children: [
84
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
85
+ import_listbox.Listbox,
86
+ {
87
+ items: optionItems,
88
+ getKey,
89
+ getLabel,
90
+ value: selectedItem,
91
+ onChange: async (next) => {
92
+ if (next) await commitValue(next.value);
93
+ },
94
+ disabled,
95
+ searchable,
96
+ matchAnchorWidth: true,
97
+ onOpenChange: setOpen,
98
+ renderTrigger: ({ open: isOpen, triggerProps }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
99
+ "button",
100
+ {
101
+ type: "button",
102
+ ...triggerProps,
103
+ className: (0, import_helpers.cn)(
104
+ "uxm-editable-cell__select-trigger",
105
+ isOpen && "uxm-editable-cell__select-trigger--open"
106
+ ),
107
+ "aria-label": ariaLabel ?? `Edit ${String(value ?? "")}`,
108
+ children: [
109
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_hover_tooltip.HoverTooltip, { content: titleText, disabled, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "uxm-editable-cell__value uxm-editable-cell__option-label", children: display }) }),
110
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "uxm-editable-cell__chevron", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icon.Icon, { glyph: "chevron-down", size: 12 }) })
111
+ ]
112
+ }
113
+ ),
114
+ renderItem: (o) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "uxm-editable-cell__option-label", children: o.label }),
115
+ footer: clearable && selectedItem ? ({ close }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
116
+ import_button.ButtonGhost,
117
+ {
118
+ className: "uxm-listbox__footer-clear-option",
119
+ onClick: () => {
120
+ commitValue("");
121
+ close();
122
+ },
123
+ children: [
124
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icon.Icon, { glyph: "close", size: 12 }),
125
+ "Clear"
126
+ ]
127
+ }
128
+ ) : void 0
129
+ }
130
+ ),
131
+ clearable && !disabled && !submitting && !isEmpty && /* Trigger ✕ — clear from the field itself (the input-family
132
+ convention), on every size: commits the empty value directly,
133
+ complementing the panel-footer Clear. Sibling of the trigger (a
134
+ button can't nest a button), absolutely positioned into the
135
+ reserved second gutter slot. Revealed only while the panel is
136
+ open (see the `--open` gate in the stylesheet) — unlike the
137
+ chevron, which also shows on hover. */
138
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
139
+ "button",
140
+ {
141
+ type: "button",
142
+ className: "uxm-editable-cell__trigger-clear",
143
+ tabIndex: -1,
144
+ onMouseDown: (e) => e.stopPropagation(),
145
+ onClick: () => void commitValue(""),
146
+ "aria-label": clearSelectionLabel,
147
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icon.Icon, { glyph: "close", size: 12 })
148
+ }
149
+ ),
150
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
151
+ import_popover.Popover,
152
+ {
153
+ open: Boolean(shownError),
154
+ onOpenChange: (next) => {
155
+ if (!next) setError(null);
156
+ },
157
+ anchor: wrapRef,
158
+ placement: "bottom-start",
159
+ closeOnEscape: false,
160
+ closeOnOutsideClick: false,
161
+ restoreFocus: false,
162
+ role: "presentation",
163
+ children: shownError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
164
+ import_banner.Banner,
165
+ {
166
+ variant: shownError.severity,
167
+ id: "uxm-editable-cell__error",
168
+ className: "uxm-editable-cell__error-banner",
169
+ children: shownError.message
170
+ }
171
+ )
172
+ }
173
+ )
174
+ ]
175
+ }
176
+ );
177
+ }
178
+ const selectedItems = Array.isArray(value) ? optionItems.filter((o) => value.includes(o.value)) : [];
179
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
180
+ "span",
181
+ {
182
+ ref: wrapRef,
183
+ className: (0, import_helpers.cn)(
184
+ "uxm-editable-cell",
185
+ `uxm-editable-cell--${size}`,
186
+ `uxm-editable-cell--align-${align}`,
187
+ `uxm-editable-cell--type-${type}`,
188
+ clearable && "uxm-editable-cell--clearable",
189
+ disabled && "uxm-editable-cell--disabled",
190
+ isEmpty && "uxm-editable-cell--empty",
191
+ open && "uxm-editable-cell--open",
192
+ className
193
+ ),
194
+ style,
195
+ children: [
196
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
197
+ import_listbox.MultiListbox,
198
+ {
199
+ items: optionItems,
200
+ getKey,
201
+ getLabel,
202
+ value: selectedItems,
203
+ onChange: (items) => void commitValue(items.map((o) => o.value)),
204
+ commitMode: "close",
205
+ required,
206
+ requiredMessage,
207
+ onRequiredViolation: (message) => setError({ message, severity: "warning" }),
208
+ disabled,
209
+ searchable,
210
+ matchAnchorWidth: true,
211
+ onOpenChange: (next) => {
212
+ setOpen(next);
213
+ if (next) setError(null);
214
+ },
215
+ renderTrigger: ({ open: isOpen, triggerProps }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
216
+ "button",
217
+ {
218
+ type: "button",
219
+ ...triggerProps,
220
+ className: (0, import_helpers.cn)(
221
+ "uxm-editable-cell__select-trigger",
222
+ isOpen && "uxm-editable-cell__select-trigger--open"
223
+ ),
224
+ "aria-label": ariaLabel ?? `Edit ${String(value ?? "")}`,
225
+ children: [
226
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_hover_tooltip.HoverTooltip, { content: titleText, disabled, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "uxm-editable-cell__value uxm-editable-cell__option-label", children: display }) }),
227
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "uxm-editable-cell__chevron", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icon.Icon, { glyph: "chevron-down", size: 12 }) })
228
+ ]
229
+ }
230
+ ),
231
+ renderItem: (o) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "uxm-editable-cell__option-label", children: o.label }),
232
+ footer: clearable ? ({ clear, selected }) => selected.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
233
+ import_button.ButtonGhost,
234
+ {
235
+ className: "uxm-listbox__footer-clear-option",
236
+ onClick: clear,
237
+ children: [
238
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icon.Icon, { glyph: "close", size: 12 }),
239
+ "Clear all"
240
+ ]
241
+ }
242
+ ) : null : void 0
243
+ }
244
+ ),
245
+ clearable && !disabled && !submitting && !isEmpty && /* Trigger ✕ — clear from the field itself (the input-family
246
+ convention), on every size: commits the empty value directly,
247
+ complementing the panel-footer Clear. Sibling of the trigger (a
248
+ button can't nest a button), absolutely positioned into the
249
+ reserved second gutter slot. Revealed only while the panel is
250
+ open (see the `--open` gate in the stylesheet) — unlike the
251
+ chevron, which also shows on hover. */
252
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
253
+ "button",
254
+ {
255
+ type: "button",
256
+ className: "uxm-editable-cell__trigger-clear",
257
+ tabIndex: -1,
258
+ onMouseDown: (e) => e.stopPropagation(),
259
+ onClick: () => void commitValue([]),
260
+ "aria-label": clearSelectionLabel,
261
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icon.Icon, { glyph: "close", size: 12 })
262
+ }
263
+ ),
264
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
265
+ import_popover.Popover,
266
+ {
267
+ open: Boolean(shownError),
268
+ onOpenChange: (next) => {
269
+ if (!next) setError(null);
270
+ },
271
+ anchor: wrapRef,
272
+ placement: "bottom-start",
273
+ closeOnEscape: false,
274
+ closeOnOutsideClick: false,
275
+ restoreFocus: false,
276
+ role: "presentation",
277
+ children: shownError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
278
+ import_banner.Banner,
279
+ {
280
+ variant: shownError.severity,
281
+ id: "uxm-editable-cell__error",
282
+ className: "uxm-editable-cell__error-banner",
283
+ children: shownError.message
284
+ }
285
+ )
286
+ }
287
+ )
288
+ ]
289
+ }
290
+ );
291
+ }
292
+ }
293
+ // Annotate the CommonJS export names for ESM import in node:
294
+ 0 && (module.exports = {
295
+ EditableCellSelectView
296
+ });
297
+ //# sourceMappingURL=editable-cell-select.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/ui/editable-cell/editable-cell-select.tsx"],"sourcesContent":["import { cn } from '@/helpers';\n\nimport { Banner } from '../banner';\nimport { ButtonGhost } from '../button';\nimport { HoverTooltip } from '../hover-tooltip';\nimport { Icon } from '../icon';\nimport { Listbox, MultiListbox, type ListboxRenderTriggerState } from '../listbox';\nimport { Popover } from '../popover';\n\nimport type { EditableCellOption } from './editable-cell.types';\nimport type { EditableCellViewProps } from './use-editable-cell';\n\n/** `type=\"select\"` / `\"multiselect\"` — a Listbox-driven trigger; no display/edit split. */\nexport function EditableCellSelectView({ props, cell }: EditableCellViewProps) {\n const {\n value,\n options,\n requiredMessage,\n disabled,\n className,\n style,\n 'aria-label': ariaLabel,\n type,\n searchable,\n clearable,\n align,\n size,\n required,\n clearSelectionLabel,\n } = props;\n const {\n submitting,\n setError,\n open,\n setOpen,\n wrapRef,\n commitValue,\n isEmpty,\n display,\n titleText,\n shownError,\n } = cell;\n\n // For select/multiselect in open state, we render a Listbox-driven UI\n if (type === 'select' || type === 'multiselect') {\n const optionItems = options ?? [];\n const getKey = (o: EditableCellOption) => o.value;\n const getLabel = (o: EditableCellOption) => o.label;\n\n if (type === 'select') {\n const selectedItem = Array.isArray(value)\n ? null\n : optionItems.find((o) => o.value === String(value ?? '')) ?? null;\n\n return (\n <span\n ref={wrapRef}\n className={cn(\n 'uxm-editable-cell',\n `uxm-editable-cell--${size}`,\n `uxm-editable-cell--align-${align}`,\n `uxm-editable-cell--type-${type}`,\n clearable && 'uxm-editable-cell--clearable',\n disabled && 'uxm-editable-cell--disabled',\n isEmpty && 'uxm-editable-cell--empty',\n open && 'uxm-editable-cell--open',\n className,\n )}\n style={style}\n >\n <Listbox<EditableCellOption>\n items={optionItems}\n getKey={getKey}\n getLabel={getLabel}\n value={selectedItem}\n onChange={async (next) => {\n if (next) await commitValue(next.value);\n }}\n disabled={disabled}\n searchable={searchable}\n matchAnchorWidth\n onOpenChange={setOpen}\n renderTrigger={({ open: isOpen, triggerProps }: ListboxRenderTriggerState<EditableCellOption>) => (\n <button\n type=\"button\"\n {...triggerProps}\n className={cn(\n 'uxm-editable-cell__select-trigger',\n isOpen && 'uxm-editable-cell__select-trigger--open',\n )}\n aria-label={ariaLabel ?? `Edit ${String(value ?? '')}`}\n >\n <HoverTooltip content={titleText} disabled={disabled}>\n <span className=\"uxm-editable-cell__value uxm-editable-cell__option-label\">\n {display}\n </span>\n </HoverTooltip>\n <span className=\"uxm-editable-cell__chevron\" aria-hidden=\"true\">\n <Icon glyph=\"chevron-down\" size={12} />\n </span>\n </button>\n )}\n renderItem={(o) => (\n <span className=\"uxm-editable-cell__option-label\">{o.label}</span>\n )}\n footer={clearable && selectedItem ? ({ close }: { close: () => void }) => (\n <ButtonGhost\n className=\"uxm-listbox__footer-clear-option\"\n onClick={() => {\n commitValue('');\n close();\n }}\n >\n <Icon glyph=\"close\" size={12} />\n Clear\n </ButtonGhost>\n ) : undefined}\n />\n {clearable && !disabled && !submitting && !isEmpty && (\n /* Trigger ✕ — clear from the field itself (the input-family\n convention), on every size: commits the empty value directly,\n complementing the panel-footer Clear. Sibling of the trigger (a\n button can't nest a button), absolutely positioned into the\n reserved second gutter slot. Revealed only while the panel is\n open (see the `--open` gate in the stylesheet) — unlike the\n chevron, which also shows on hover. */\n <button\n type=\"button\"\n className=\"uxm-editable-cell__trigger-clear\"\n // Out of the tab order, same as every in-field clear here.\n tabIndex={-1}\n // This button is a SIBLING of the Listbox trigger, so it sits\n // outside the refs `useDismiss` treats as \"inside\" — and dismiss\n // runs on mousedown, i.e. BEFORE this click. Left alone, pressing\n // ✕ would first dismiss the panel and only then clear. Stop the\n // mousedown here so the clear below is the single thing that acts.\n onMouseDown={(e) => e.stopPropagation()}\n onClick={() => void commitValue('')}\n aria-label={clearSelectionLabel}\n >\n <Icon glyph=\"close\" size={12} />\n </button>\n )}\n <Popover\n open={Boolean(shownError)}\n onOpenChange={(next) => {\n if (!next) setError(null);\n }}\n anchor={wrapRef}\n placement=\"bottom-start\"\n closeOnEscape={false}\n closeOnOutsideClick={false}\n restoreFocus={false}\n role=\"presentation\"\n >\n {shownError && (\n <Banner\n variant={shownError.severity}\n id=\"uxm-editable-cell__error\"\n className=\"uxm-editable-cell__error-banner\"\n >\n {shownError.message}\n </Banner>\n )}\n </Popover>\n </span>\n );\n }\n\n // multiselect. A cell is a commit boundary, so this branch opts into\n // MultiListbox's staged mode (`commitMode=\"close\"`: draft while open, one\n // commit on close) — a required cell then survives \"clear all → pick one\"\n // and N picks are one `onCommit`. It just hands over the committed\n // selection and commits the final array back.\n const selectedItems = Array.isArray(value)\n ? optionItems.filter((o) => value.includes(o.value))\n : [];\n\n return (\n <span\n ref={wrapRef}\n className={cn(\n 'uxm-editable-cell',\n `uxm-editable-cell--${size}`,\n `uxm-editable-cell--align-${align}`,\n `uxm-editable-cell--type-${type}`,\n clearable && 'uxm-editable-cell--clearable',\n disabled && 'uxm-editable-cell--disabled',\n isEmpty && 'uxm-editable-cell--empty',\n open && 'uxm-editable-cell--open',\n className,\n )}\n style={style}\n >\n <MultiListbox<EditableCellOption>\n items={optionItems}\n getKey={getKey}\n getLabel={getLabel}\n value={selectedItems}\n onChange={(items) => void commitValue(items.map((o) => o.value))}\n // Commit on close, not per toggle — see the note above.\n commitMode=\"close\"\n required={required}\n requiredMessage={requiredMessage}\n // MultiListbox owns the empty rule for multi (shared with every\n // picker); route its violation into this cell's error Banner.\n onRequiredViolation={(message) => setError({ message, severity: 'warning' })}\n disabled={disabled}\n searchable={searchable}\n matchAnchorWidth\n // Clear a stale required warning when the panel reopens for a fresh edit.\n onOpenChange={(next) => {\n setOpen(next);\n if (next) setError(null);\n }}\n renderTrigger={({ open: isOpen, triggerProps }: ListboxRenderTriggerState<EditableCellOption>) => (\n <button\n type=\"button\"\n {...triggerProps}\n className={cn(\n 'uxm-editable-cell__select-trigger',\n isOpen && 'uxm-editable-cell__select-trigger--open',\n )}\n aria-label={ariaLabel ?? `Edit ${String(value ?? '')}`}\n >\n <HoverTooltip content={titleText} disabled={disabled}>\n <span className=\"uxm-editable-cell__value uxm-editable-cell__option-label\">\n {display}\n </span>\n </HoverTooltip>\n <span className=\"uxm-editable-cell__chevron\" aria-hidden=\"true\">\n <Icon glyph=\"chevron-down\" size={12} />\n </span>\n </button>\n )}\n renderItem={(o) => (\n <span className=\"uxm-editable-cell__option-label\">{o.label}</span>\n )}\n footer={clearable ? ({ clear, selected }: { clear: () => void; selected: EditableCellOption[] }) =>\n selected.length > 0 ? (\n <ButtonGhost\n className=\"uxm-listbox__footer-clear-option\"\n // `clear` (from MultiListbox) empties the draft and keeps the\n // panel open, so \"clear all then pick one\" works even on a\n // required cell — the empty state is transient and never\n // reaches `validate` / `onCommit`. `selected` is the live\n // draft, so the button hides itself once nothing is picked.\n onClick={clear}\n >\n <Icon glyph=\"close\" size={12} />\n Clear all\n </ButtonGhost>\n ) : null\n : undefined}\n />\n {clearable && !disabled && !submitting && !isEmpty && (\n /* Trigger ✕ — clear from the field itself (the input-family\n convention), on every size: commits the empty value directly,\n complementing the panel-footer Clear. Sibling of the trigger (a\n button can't nest a button), absolutely positioned into the\n reserved second gutter slot. Revealed only while the panel is\n open (see the `--open` gate in the stylesheet) — unlike the\n chevron, which also shows on hover. */\n <button\n type=\"button\"\n className=\"uxm-editable-cell__trigger-clear\"\n // Out of the tab order, same as every in-field clear here.\n tabIndex={-1}\n // Same sibling-of-the-trigger problem as the select ✕ above, but\n // costlier here: `useDismiss` fires on mousedown, and this panel\n // runs `commitMode=\"close\"`, so an unswallowed mousedown would\n // commit the STAGED DRAFT first and only then clear — two commits\n // for one press, and if the first is still in flight the\n // re-entrancy guard in `commitValue` drops the clear entirely.\n // Stopping it leaves the panel open, which is deliberate and\n // matches the footer's \"Clear all\": clear, then pick afresh.\n // MultiListbox re-seeds its draft from `value` under an open panel,\n // so the later close commits the cleared set, not the stale draft.\n onMouseDown={(e) => e.stopPropagation()}\n onClick={() => void commitValue([])}\n aria-label={clearSelectionLabel}\n >\n <Icon glyph=\"close\" size={12} />\n </button>\n )}\n <Popover\n open={Boolean(shownError)}\n onOpenChange={(next) => {\n if (!next) setError(null);\n }}\n anchor={wrapRef}\n placement=\"bottom-start\"\n closeOnEscape={false}\n closeOnOutsideClick={false}\n restoreFocus={false}\n role=\"presentation\"\n >\n {shownError && (\n <Banner\n variant={shownError.severity}\n id=\"uxm-editable-cell__error\"\n className=\"uxm-editable-cell__error-banner\"\n >\n {shownError.message}\n </Banner>\n )}\n </Popover>\n </span>\n );\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,4 @@
1
+ import type { EditableCellViewProps } from './use-editable-cell.js';
2
+ /** `type="select"` / `"multiselect"` — a Listbox-driven trigger; no display/edit split. */
3
+ export declare function EditableCellSelectView({ props, cell }: EditableCellViewProps): import("react").JSX.Element | undefined;
4
+ //# sourceMappingURL=editable-cell-select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editable-cell-select.d.ts","sourceRoot":"","sources":["../../../src/ui/editable-cell/editable-cell-select.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEjE,2FAA2F;AAC3F,wBAAgB,sBAAsB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,qBAAqB,2CAyS5E"}