sellmate-design-system-react 9.0.0-beta.55 → 9.0.0-beta.57

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.js CHANGED
@@ -8,7 +8,7 @@ import { createPortal } from 'react-dom';
8
8
  import * as RCheckbox from '@radix-ui/react-checkbox';
9
9
  import { createRoot } from 'react-dom/client';
10
10
  import * as RTooltip from '@radix-ui/react-tooltip';
11
- import * as RDropdown2 from '@radix-ui/react-dropdown-menu';
11
+ import * as RDropdown3 from '@radix-ui/react-dropdown-menu';
12
12
  import * as RSwitch from '@radix-ui/react-switch';
13
13
  import * as RDialog from '@radix-ui/react-dialog';
14
14
  import * as Ariakit from '@ariakit/react';
@@ -343,6 +343,43 @@ var Icon_alert = (p) => {
343
343
  }
344
344
  );
345
345
  };
346
+ var Icon_alignCenter = (p) => {
347
+ const { size = 24, ...rest } = p;
348
+ return /* @__PURE__ */ jsxs(
349
+ "svg",
350
+ {
351
+ width: size,
352
+ height: size,
353
+ viewBox: "0 0 24 24",
354
+ fill: "none",
355
+ xmlns: "http://www.w3.org/2000/svg",
356
+ ...rest,
357
+ children: [
358
+ /* @__PURE__ */ jsx(
359
+ "path",
360
+ {
361
+ d: "M20 16.25C20.4142 16.25 20.75 16.5858 20.75 17C20.75 17.4142 20.4142 17.75 20 17.75H4C3.58579 17.75 3.25 17.4142 3.25 17C3.25 16.5858 3.58579 16.25 4 16.25H20Z",
362
+ fill: "currentColor"
363
+ }
364
+ ),
365
+ /* @__PURE__ */ jsx(
366
+ "path",
367
+ {
368
+ d: "M16 11.25C16.4142 11.25 16.75 11.5858 16.75 12C16.75 12.4142 16.4142 12.75 16 12.75H7C6.58579 12.75 6.25 12.4142 6.25 12C6.25 11.5858 6.58579 11.25 7 11.25H16Z",
369
+ fill: "currentColor"
370
+ }
371
+ ),
372
+ /* @__PURE__ */ jsx(
373
+ "path",
374
+ {
375
+ d: "M21.4004 6.25C21.8144 6.25021 22.1504 6.58592 22.1504 7C22.1504 7.41408 21.8144 7.74979 21.4004 7.75H3C2.58579 7.75 2.25 7.41421 2.25 7C2.25 6.58579 2.58579 6.25 3 6.25H21.4004Z",
376
+ fill: "currentColor"
377
+ }
378
+ )
379
+ ]
380
+ }
381
+ );
382
+ };
346
383
  var Icon_alignKorean = (p) => {
347
384
  const { size = 24, ...rest } = p;
348
385
  return /* @__PURE__ */ jsxs(
@@ -382,6 +419,147 @@ var Icon_alignKorean = (p) => {
382
419
  }
383
420
  );
384
421
  };
422
+ var Icon_alignLeft = (p) => {
423
+ const { size = 24, ...rest } = p;
424
+ return /* @__PURE__ */ jsxs(
425
+ "svg",
426
+ {
427
+ width: size,
428
+ height: size,
429
+ viewBox: "0 0 24 24",
430
+ fill: "none",
431
+ xmlns: "http://www.w3.org/2000/svg",
432
+ ...rest,
433
+ children: [
434
+ /* @__PURE__ */ jsx(
435
+ "path",
436
+ {
437
+ d: "M19 16.25C19.4142 16.25 19.75 16.5858 19.75 17C19.75 17.4142 19.4142 17.75 19 17.75H3C2.58579 17.75 2.25 17.4142 2.25 17C2.25 16.5858 2.58579 16.25 3 16.25H19Z",
438
+ fill: "currentColor"
439
+ }
440
+ ),
441
+ /* @__PURE__ */ jsx(
442
+ "path",
443
+ {
444
+ d: "M12 11.25C12.4142 11.25 12.75 11.5858 12.75 12C12.75 12.4142 12.4142 12.75 12 12.75H3C2.58579 12.75 2.25 12.4142 2.25 12C2.25 11.5858 2.58579 11.25 3 11.25H12Z",
445
+ fill: "currentColor"
446
+ }
447
+ ),
448
+ /* @__PURE__ */ jsx(
449
+ "path",
450
+ {
451
+ d: "M21.4004 6.25C21.8144 6.25021 22.1504 6.58592 22.1504 7C22.1504 7.41408 21.8144 7.74979 21.4004 7.75H3C2.58579 7.75 2.25 7.41421 2.25 7C2.25 6.58579 2.58579 6.25 3 6.25H21.4004Z",
452
+ fill: "currentColor"
453
+ }
454
+ )
455
+ ]
456
+ }
457
+ );
458
+ };
459
+ var Icon_alignMiddle = (p) => {
460
+ const { size = 24, ...rest } = p;
461
+ return /* @__PURE__ */ jsxs(
462
+ "svg",
463
+ {
464
+ width: size,
465
+ height: size,
466
+ viewBox: "0 0 24 24",
467
+ fill: "none",
468
+ xmlns: "http://www.w3.org/2000/svg",
469
+ ...rest,
470
+ children: [
471
+ /* @__PURE__ */ jsx(
472
+ "path",
473
+ {
474
+ d: "M11.4844 13.9551C11.7735 13.6819 12.2265 13.6819 12.5156 13.9551L15.5156 16.79C15.8165 17.0746 15.8294 17.5496 15.5449 17.8506C15.2604 18.1515 14.7854 18.1653 14.4844 17.8809L12.75 16.2422V20.5C12.75 20.9142 12.4142 21.25 12 21.25C11.5858 21.25 11.25 20.9142 11.25 20.5V16.2422L9.51562 17.8809C9.21463 18.1653 8.73961 18.1515 8.45508 17.8506C8.17061 17.5496 8.18347 17.0746 8.48438 16.79L11.4844 13.9551Z",
475
+ fill: "currentColor"
476
+ }
477
+ ),
478
+ /* @__PURE__ */ jsx(
479
+ "path",
480
+ {
481
+ d: "M21.2002 11.25C21.6142 11.2502 21.9502 11.5859 21.9502 12C21.9502 12.4141 21.6142 12.7498 21.2002 12.75H2.7998C2.38568 12.7499 2.0498 12.4142 2.0498 12C2.0498 11.5858 2.38568 11.2501 2.7998 11.25H21.2002Z",
482
+ fill: "currentColor"
483
+ }
484
+ ),
485
+ /* @__PURE__ */ jsx(
486
+ "path",
487
+ {
488
+ d: "M12 2.75C12.4142 2.75 12.75 3.08579 12.75 3.5V7.75781L14.4844 6.11914C14.7854 5.83467 15.2604 5.8485 15.5449 6.14941C15.8294 6.45041 15.8165 6.92543 15.5156 7.20996L12.5156 10.0449C12.2265 10.3182 11.7735 10.3182 11.4844 10.0449L8.48438 7.20996C8.18347 6.92543 8.17061 6.45041 8.45508 6.14941C8.73961 5.8485 9.21463 5.83467 9.51562 6.11914L11.25 7.75781V3.5C11.25 3.08579 11.5858 2.75 12 2.75Z",
489
+ fill: "currentColor"
490
+ }
491
+ )
492
+ ]
493
+ }
494
+ );
495
+ };
496
+ var Icon_alignRight = (p) => {
497
+ const { size = 24, ...rest } = p;
498
+ return /* @__PURE__ */ jsxs(
499
+ "svg",
500
+ {
501
+ width: size,
502
+ height: size,
503
+ viewBox: "0 0 24 24",
504
+ fill: "none",
505
+ xmlns: "http://www.w3.org/2000/svg",
506
+ ...rest,
507
+ children: [
508
+ /* @__PURE__ */ jsx(
509
+ "path",
510
+ {
511
+ d: "M21 16.25C21.4142 16.25 21.75 16.5858 21.75 17C21.75 17.4142 21.4142 17.75 21 17.75H5C4.58579 17.75 4.25 17.4142 4.25 17C4.25 16.5858 4.58579 16.25 5 16.25H21Z",
512
+ fill: "currentColor"
513
+ }
514
+ ),
515
+ /* @__PURE__ */ jsx(
516
+ "path",
517
+ {
518
+ d: "M21 11.25C21.4142 11.25 21.75 11.5858 21.75 12C21.75 12.4142 21.4142 12.75 21 12.75H12C11.5858 12.75 11.25 12.4142 11.25 12C11.25 11.5858 11.5858 11.25 12 11.25H21Z",
519
+ fill: "currentColor"
520
+ }
521
+ ),
522
+ /* @__PURE__ */ jsx(
523
+ "path",
524
+ {
525
+ d: "M21.4004 6.25C21.8144 6.25021 22.1504 6.58592 22.1504 7C22.1504 7.41408 21.8144 7.74979 21.4004 7.75H3C2.58579 7.75 2.25 7.41421 2.25 7C2.25 6.58579 2.58579 6.25 3 6.25H21.4004Z",
526
+ fill: "currentColor"
527
+ }
528
+ )
529
+ ]
530
+ }
531
+ );
532
+ };
533
+ var Icon_alignTop = (p) => {
534
+ const { size = 24, ...rest } = p;
535
+ return /* @__PURE__ */ jsxs(
536
+ "svg",
537
+ {
538
+ width: size,
539
+ height: size,
540
+ viewBox: "0 0 24 24",
541
+ fill: "none",
542
+ xmlns: "http://www.w3.org/2000/svg",
543
+ ...rest,
544
+ children: [
545
+ /* @__PURE__ */ jsx(
546
+ "path",
547
+ {
548
+ d: "M12 6.1499C12.2017 6.1499 12.3951 6.23132 12.5361 6.37549L18.5361 12.519C18.8254 12.8153 18.8204 13.2901 18.5244 13.5796C18.2281 13.869 17.7533 13.8631 17.4639 13.5669L12.75 8.7417V19.8999C12.75 20.3141 12.4142 20.6499 12 20.6499C11.5858 20.6499 11.25 20.3141 11.25 19.8999V8.7417L6.53613 13.5669C6.24671 13.8631 5.77189 13.869 5.47559 13.5796C5.1796 13.2901 5.17456 12.8153 5.46387 12.519L11.4639 6.37549C11.6049 6.23132 11.7983 6.1499 12 6.1499Z",
549
+ fill: "currentColor"
550
+ }
551
+ ),
552
+ /* @__PURE__ */ jsx(
553
+ "path",
554
+ {
555
+ d: "M21.2002 3.24951C21.6142 3.24972 21.9502 3.58641 21.9502 4.00049C21.9499 4.41435 21.6141 4.75028 21.2002 4.75049H2.7998C2.38584 4.75039 2.05007 4.41442 2.0498 4.00049C2.0498 3.58634 2.38568 3.24961 2.7998 3.24951H21.2002Z",
556
+ fill: "currentColor"
557
+ }
558
+ )
559
+ ]
560
+ }
561
+ );
562
+ };
385
563
  var Icon_archive = (p) => {
386
564
  const { size = 24, ...rest } = p;
387
565
  return /* @__PURE__ */ jsx(
@@ -3400,7 +3578,12 @@ var ICONS = {
3400
3578
  account: Icon_account,
3401
3579
  add: Icon_add,
3402
3580
  alert: Icon_alert,
3581
+ alignCenter: Icon_alignCenter,
3403
3582
  alignKorean: Icon_alignKorean,
3583
+ alignLeft: Icon_alignLeft,
3584
+ alignMiddle: Icon_alignMiddle,
3585
+ alignRight: Icon_alignRight,
3586
+ alignTop: Icon_alignTop,
3404
3587
  archive: Icon_archive,
3405
3588
  arrowDown: Icon_arrowDown,
3406
3589
  arrowLeft: Icon_arrowLeft,
@@ -4043,7 +4226,8 @@ var TAG_COLORS = [
4043
4226
  "green",
4044
4227
  "blue",
4045
4228
  "darkblue",
4046
- "indigo"
4229
+ "indigo",
4230
+ "purple"
4047
4231
  ];
4048
4232
  var TAG_SIZE_CONFIG = {
4049
4233
  xs: {
@@ -6165,6 +6349,13 @@ function SDraggableListInner({
6165
6349
  );
6166
6350
  }
6167
6351
  var SDraggableList = /* @__PURE__ */ forwardRef(SDraggableListInner);
6352
+ function useInertRef(inert) {
6353
+ const ref = useRef(null);
6354
+ useEffect(() => {
6355
+ ref.current?.toggleAttribute("inert", inert);
6356
+ }, [inert]);
6357
+ return ref;
6358
+ }
6168
6359
  var SExpansionItemDescendantContext = /* @__PURE__ */ createContext(
6169
6360
  null
6170
6361
  );
@@ -6196,6 +6387,7 @@ var SExpansionItem = /* @__PURE__ */ forwardRef(
6196
6387
  const [hovered, setHovered] = useState(false);
6197
6388
  const parentDescendantContext = useContext(SExpansionItemDescendantContext);
6198
6389
  const isExpanded = expanded ?? internalExpanded;
6390
+ const bodyRef = useInertRef(!isExpanded);
6199
6391
  const isSelected = isExpanded && (selected || expandedDescendantCount === 0);
6200
6392
  const hasChevronInteraction = interaction === "chevron";
6201
6393
  const showInteractionChevron = hasChevronInteraction && !disabled && (isSelected || hovered);
@@ -6319,6 +6511,7 @@ var SExpansionItem = /* @__PURE__ */ forwardRef(
6319
6511
  "div",
6320
6512
  {
6321
6513
  id,
6514
+ ref: bodyRef,
6322
6515
  "aria-hidden": !isExpanded,
6323
6516
  className: cn(
6324
6517
  "grid overflow-hidden bg-(--cmp-listExpansionItem-body-bg) transition-[grid-template-rows] duration-200 ease-out motion-reduce:transition-none",
@@ -6764,11 +6957,29 @@ function TreeConnector({
6764
6957
  ] })
6765
6958
  ] });
6766
6959
  }
6960
+ function TreeBranch({ expanded, children }) {
6961
+ const branchRef = useInertRef(!expanded);
6962
+ return /* @__PURE__ */ jsx(
6963
+ "div",
6964
+ {
6965
+ ref: branchRef,
6966
+ "aria-hidden": !expanded,
6967
+ className: cn(
6968
+ "grid w-full overflow-hidden transition-[grid-template-rows] duration-200 ease-out motion-reduce:transition-none",
6969
+ expanded ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
6970
+ ),
6971
+ children: /* @__PURE__ */ jsx("div", { className: "min-h-0 overflow-hidden", children })
6972
+ }
6973
+ );
6974
+ }
6767
6975
  function STreeAllItem({
6768
6976
  selected,
6769
6977
  indeterminate,
6770
6978
  border,
6771
6979
  size,
6980
+ rowId,
6981
+ tabIndex,
6982
+ onKeyDown,
6772
6983
  onSelect
6773
6984
  }) {
6774
6985
  const checkboxValue = indeterminate ? null : selected;
@@ -6780,6 +6991,9 @@ function STreeAllItem({
6780
6991
  role: "treeitem",
6781
6992
  "aria-level": 1,
6782
6993
  "aria-selected": selected,
6994
+ "data-tree-row": rowId,
6995
+ tabIndex,
6996
+ onKeyDown,
6783
6997
  onClick: onSelect,
6784
6998
  className: cn(
6785
6999
  "group/tree-item box-border flex w-full cursor-pointer items-center overflow-hidden bg-(--cmp-tree-item-bg-default) px-(--cmp-tree-item-paddingX) text-left hover:bg-(--cmp-tree-item-bg-hover)",
@@ -6965,6 +7179,34 @@ var STreeImpl = /* @__PURE__ */ forwardRef(function STree({
6965
7179
  const someSelected = selectableIds.some((id) => selectedSet.has(id));
6966
7180
  const allIndeterminate = someSelected && !allSelected;
6967
7181
  const showAllItem = selectable && showSelectAll;
7182
+ const visibleRows = useMemo(() => {
7183
+ const rows = [];
7184
+ if (showAllItem) {
7185
+ rows.push({ id: TREE_ALL_NODE.id, node: TREE_ALL_NODE, parentId: null, expanded: false });
7186
+ }
7187
+ const walk = (nodes, parentId) => {
7188
+ nodes.forEach((node) => {
7189
+ const expanded = !!node.children?.length && expandedSet.has(node.id);
7190
+ rows.push({ id: node.id, node, parentId, expanded });
7191
+ if (expanded) walk(node.children, node.id);
7192
+ });
7193
+ };
7194
+ walk(items, null);
7195
+ return rows;
7196
+ }, [items, expandedSet, showAllItem]);
7197
+ const [focusedId, setFocusedId] = useState(null);
7198
+ const activeRowId = focusedId != null && visibleRows.some((row) => row.id === focusedId) ? focusedId : visibleRows[0]?.id ?? null;
7199
+ const treeRef = useRef(null);
7200
+ const focusRow = (id) => {
7201
+ setFocusedId(id);
7202
+ const rows = treeRef.current?.querySelectorAll("[data-tree-row]") ?? [];
7203
+ for (const row of rows) {
7204
+ if (row.dataset.treeRow === id) {
7205
+ row.focus();
7206
+ return;
7207
+ }
7208
+ }
7209
+ };
6968
7210
  const updateExpanded = (node) => {
6969
7211
  const next = new Set(currentExpandedIds);
6970
7212
  if (next.has(node.id)) next.delete(node.id);
@@ -6998,6 +7240,59 @@ var STreeImpl = /* @__PURE__ */ forwardRef(function STree({
6998
7240
  if (value === void 0) setInternalValue(orderedIds);
6999
7241
  onValueChange?.(orderedIds, TREE_ALL_NODE);
7000
7242
  };
7243
+ const handleTreeKeyDown = (event) => {
7244
+ const target = event.target;
7245
+ const rowId = target.dataset?.treeRow;
7246
+ if (rowId == null) return;
7247
+ const index = visibleRows.findIndex((row2) => row2.id === rowId);
7248
+ if (index < 0) return;
7249
+ const row = visibleRows[index];
7250
+ const hasChildren = !!row.node.children?.length;
7251
+ switch (event.key) {
7252
+ case "ArrowDown": {
7253
+ const next = visibleRows[index + 1];
7254
+ if (next) focusRow(next.id);
7255
+ break;
7256
+ }
7257
+ case "ArrowUp": {
7258
+ const prev = visibleRows[index - 1];
7259
+ if (prev) focusRow(prev.id);
7260
+ break;
7261
+ }
7262
+ case "ArrowRight": {
7263
+ if (!hasChildren || row.node.disabled) return;
7264
+ if (!row.expanded) updateExpanded(row.node);
7265
+ else if (visibleRows[index + 1]) focusRow(visibleRows[index + 1].id);
7266
+ break;
7267
+ }
7268
+ case "ArrowLeft": {
7269
+ if (hasChildren && row.expanded && !row.node.disabled) updateExpanded(row.node);
7270
+ else if (row.parentId != null) focusRow(row.parentId);
7271
+ else return;
7272
+ break;
7273
+ }
7274
+ case "Home": {
7275
+ if (visibleRows[0]) focusRow(visibleRows[0].id);
7276
+ break;
7277
+ }
7278
+ case "End": {
7279
+ const last = visibleRows[visibleRows.length - 1];
7280
+ if (last) focusRow(last.id);
7281
+ break;
7282
+ }
7283
+ case "Enter":
7284
+ case " ": {
7285
+ if (row.id === TREE_ALL_NODE.id) updateAllSelected();
7286
+ else if (selectable) updateSelected(row.node);
7287
+ else if (hasChildren && !row.node.disabled) updateExpanded(row.node);
7288
+ else return;
7289
+ break;
7290
+ }
7291
+ default:
7292
+ return;
7293
+ }
7294
+ event.preventDefault();
7295
+ };
7001
7296
  const renderNodes = (nodes, depth = 1, ancestorLast = []) => nodes.map((node, index) => {
7002
7297
  const isLast = index === nodes.length - 1;
7003
7298
  const isExpanded = expandedSet.has(node.id);
@@ -7006,6 +7301,9 @@ var STreeImpl = /* @__PURE__ */ forwardRef(function STree({
7006
7301
  /* @__PURE__ */ jsx(
7007
7302
  STreeItem2,
7008
7303
  {
7304
+ "data-tree-row": node.id,
7305
+ tabIndex: activeRowId === node.id ? 0 : -1,
7306
+ onKeyDown: handleTreeKeyDown,
7009
7307
  node,
7010
7308
  depth,
7011
7309
  last: isLast,
@@ -7023,30 +7321,31 @@ var STreeImpl = /* @__PURE__ */ forwardRef(function STree({
7023
7321
  onTreeSelect: updateSelected
7024
7322
  }
7025
7323
  ),
7026
- node.children?.length ? /* @__PURE__ */ jsx(
7027
- "div",
7028
- {
7029
- "aria-hidden": !isExpanded,
7030
- className: cn(
7031
- "grid w-full overflow-hidden transition-[grid-template-rows] duration-200 ease-out motion-reduce:transition-none",
7032
- isExpanded ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
7033
- ),
7034
- children: /* @__PURE__ */ jsx("div", { className: "min-h-0 overflow-hidden", children: renderNodes(node.children, depth + 1, [...ancestorLast, isLast]) })
7035
- }
7036
- ) : null
7324
+ node.children?.length ? /* @__PURE__ */ jsx(TreeBranch, { expanded: isExpanded, children: renderNodes(node.children, depth + 1, [...ancestorLast, isLast]) }) : null
7037
7325
  ] }, node.id);
7038
7326
  });
7039
7327
  return /* @__PURE__ */ jsxs(
7040
7328
  "div",
7041
7329
  {
7042
- ref,
7330
+ ref: (node) => {
7331
+ treeRef.current = node;
7332
+ if (typeof ref === "function") ref(node);
7333
+ else if (ref) ref.current = node;
7334
+ },
7043
7335
  role: "tree",
7044
7336
  className: cn("flex w-full flex-col items-start bg-(--cmp-tree-item-bg-default)", className),
7337
+ onFocus: (event) => {
7338
+ const rowId = event.target.closest?.("[data-tree-row]")?.getAttribute("data-tree-row");
7339
+ if (rowId != null) setFocusedId(rowId);
7340
+ },
7045
7341
  ...rest,
7046
7342
  children: [
7047
7343
  showAllItem && /* @__PURE__ */ jsx(
7048
7344
  STreeAllItem,
7049
7345
  {
7346
+ rowId: TREE_ALL_NODE.id,
7347
+ tabIndex: activeRowId === TREE_ALL_NODE.id ? 0 : -1,
7348
+ onKeyDown: handleTreeKeyDown,
7050
7349
  selected: allSelected,
7051
7350
  indeterminate: allIndeterminate,
7052
7351
  border,
@@ -7816,10 +8115,11 @@ var SLinearProgress = /* @__PURE__ */ forwardRef(
7816
8115
  // src/lib/global-overlay.ts
7817
8116
  var GLOBAL_OVERLAY_ATTR = "data-s-global-overlay";
7818
8117
  var globalOverlayProps = { [GLOBAL_OVERLAY_ATTR]: "" };
8118
+ var ELEMENT_NODE = 1;
7819
8119
  function isFromGlobalOverlay(event) {
7820
8120
  const detail = event.detail;
7821
8121
  const target = detail?.originalEvent?.target ?? event.target;
7822
- const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
8122
+ const element = target == null ? null : target.nodeType === ELEMENT_NODE ? target : target.parentElement ?? null;
7823
8123
  return !!element?.closest(`[${GLOBAL_OVERLAY_ATTR}]`);
7824
8124
  }
7825
8125
  var SLoadingContainer = /* @__PURE__ */ forwardRef(
@@ -8168,8 +8468,8 @@ var SDropdownButtonImpl = /* @__PURE__ */ forwardRef(
8168
8468
  "border-[color:var(--dd-border)] bg-[var(--dd-bg)] text-[color:var(--dd-text)]",
8169
8469
  disabled ? "cursor-not-allowed" : "cursor-pointer hover:bg-[var(--dd-bg-hover)]"
8170
8470
  );
8171
- const menu = /* @__PURE__ */ jsx(RDropdown2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
8172
- RDropdown2.Content,
8471
+ const menu = /* @__PURE__ */ jsx(RDropdown3.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
8472
+ RDropdown3.Content,
8173
8473
  {
8174
8474
  sideOffset: 4,
8175
8475
  align: "start",
@@ -8185,7 +8485,7 @@ var SDropdownButtonImpl = /* @__PURE__ */ forwardRef(
8185
8485
  ),
8186
8486
  style: split ? { minWidth: clampToAvailableWidth(splitWidth, DROPDOWN_AVAILABLE_WIDTH) } : void 0,
8187
8487
  children: items.map((it) => /* @__PURE__ */ jsxs(
8188
- RDropdown2.Item,
8488
+ RDropdown3.Item,
8189
8489
  {
8190
8490
  disabled: it.disabled,
8191
8491
  onSelect: () => onItemClick?.(it.value),
@@ -8206,7 +8506,7 @@ var SDropdownButtonImpl = /* @__PURE__ */ forwardRef(
8206
8506
  }
8207
8507
  ) });
8208
8508
  return /* @__PURE__ */ jsxs(
8209
- RDropdown2.Root,
8509
+ RDropdown3.Root,
8210
8510
  {
8211
8511
  modal: !insideModal,
8212
8512
  open,
@@ -8238,7 +8538,7 @@ var SDropdownButtonImpl = /* @__PURE__ */ forwardRef(
8238
8538
  children: label
8239
8539
  }
8240
8540
  ),
8241
- /* @__PURE__ */ jsx(RDropdown2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(
8541
+ /* @__PURE__ */ jsx(RDropdown3.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(
8242
8542
  "button",
8243
8543
  {
8244
8544
  ref: splitToggleRef,
@@ -8257,7 +8557,7 @@ var SDropdownButtonImpl = /* @__PURE__ */ forwardRef(
8257
8557
  ) })
8258
8558
  ]
8259
8559
  }
8260
- ) : /* @__PURE__ */ jsx(RDropdown2.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
8560
+ ) : /* @__PURE__ */ jsx(RDropdown3.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
8261
8561
  "button",
8262
8562
  {
8263
8563
  type: "button",
@@ -13258,10 +13558,9 @@ function todayStr() {
13258
13558
  function formatDate(year, month, day) {
13259
13559
  return `${year}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
13260
13560
  }
13261
- function calcYearMonth(year, month, dir) {
13262
- if (dir === "prev")
13263
- return month === 1 ? { year: year - 1, month: 12 } : { year, month: month - 1 };
13264
- return month === 12 ? { year: year + 1, month: 1 } : { year, month: month + 1 };
13561
+ function calcYearMonth(year, month, dir, step = 1) {
13562
+ const index = year * 12 + (month - 1) + (dir === "prev" ? -step : step);
13563
+ return { year: Math.floor(index / 12), month: index % 12 + 1 };
13265
13564
  }
13266
13565
  function monthCells(year, month) {
13267
13566
  const firstDayIndex = new Date(year, month - 1, 1).getDay();
@@ -14246,6 +14545,9 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
14246
14545
  const [open, setOpen] = useState(false);
14247
14546
  const [pendingOpen, setPendingOpen] = useState(false);
14248
14547
  const [focusedIndex, setFocusedIndex] = useState(-1);
14548
+ const baseId = useId();
14549
+ const listboxId = `${baseId}-listbox`;
14550
+ const activeOptionId = `${baseId}-active-option`;
14249
14551
  const [win, setWin] = useState({ start: 0, end: 0, top: 0, bottom: 0 });
14250
14552
  const winRef = useRef(win);
14251
14553
  winRef.current = win;
@@ -14331,13 +14633,15 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
14331
14633
  setPendingOpen(false);
14332
14634
  commitOpen(true);
14333
14635
  }, [insideModal, pendingOpen, portalContainer]);
14636
+ const requestOpenRef = useRef(requestOpen);
14637
+ requestOpenRef.current = requestOpen;
14334
14638
  useImperativeHandle(
14335
14639
  ref,
14336
14640
  () => ({
14337
14641
  focus: () => triggerRef.current?.focus(),
14338
- open: () => requestOpen(true)
14642
+ open: () => requestOpenRef.current(true)
14339
14643
  }),
14340
- [insideModal, portalContainer]
14644
+ []
14341
14645
  );
14342
14646
  useFormField({
14343
14647
  name,
@@ -14675,6 +14979,8 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
14675
14979
  disabled: effectiveDisabled,
14676
14980
  "aria-haspopup": "listbox",
14677
14981
  "aria-expanded": open,
14982
+ "aria-controls": open ? listboxId : void 0,
14983
+ "aria-activedescendant": open && focusedIndex >= 0 ? activeOptionId : void 0,
14678
14984
  onClick: () => requestOpen(!open),
14679
14985
  onKeyDown: handleKeyDown,
14680
14986
  className: "flex h-full w-full cursor-pointer items-center justify-between gap-[8px] bg-transparent px-[12px] text-left text-[12px] leading-[20px] outline-none disabled:cursor-not-allowed",
@@ -14801,7 +15107,9 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
14801
15107
  onValueChange: setSearch,
14802
15108
  onKeyDown: handleKeyDown,
14803
15109
  placeholder: "\uAC80\uC0C9",
14804
- clearable: true
15110
+ clearable: true,
15111
+ "aria-controls": listboxId,
15112
+ "aria-activedescendant": focusedIndex >= 0 ? activeOptionId : void 0
14805
15113
  }
14806
15114
  )
14807
15115
  }
@@ -14809,6 +15117,8 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
14809
15117
  hasItems ? /* @__PURE__ */ jsx(
14810
15118
  ItemList,
14811
15119
  {
15120
+ listboxId,
15121
+ activeOptionId,
14812
15122
  items: visibleItems,
14813
15123
  indexOffset: windowStart,
14814
15124
  topSpacer: win.top,
@@ -14857,6 +15167,8 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
14857
15167
  });
14858
15168
  var SSelect2 = /* @__PURE__ */ withDisplayName(SSelectImpl, "SSelect");
14859
15169
  function ItemList({
15170
+ listboxId,
15171
+ activeOptionId,
14860
15172
  items,
14861
15173
  indexOffset,
14862
15174
  topSpacer,
@@ -14882,12 +15194,13 @@ function ItemList({
14882
15194
  "disabled:cursor-not-allowed disabled:text-[color:var(--cmp-listBoxItem-content-disabled)]"
14883
15195
  );
14884
15196
  const activeClass = "hover:bg-[var(--cmp-listBoxItem-bg-hover)] hover:text-[color:var(--cmp-listBoxItem-content-hover)] focus-visible:bg-[var(--cmp-listBoxItem-bg-hover)] focus-visible:text-[color:var(--cmp-listBoxItem-content-hover)]";
14885
- return /* @__PURE__ */ jsxs("div", { role: "listbox", "aria-multiselectable": multi || void 0, children: [
15197
+ return /* @__PURE__ */ jsxs("div", { id: listboxId, role: "listbox", "aria-multiselectable": multi || void 0, children: [
14886
15198
  showSelectAll && /* @__PURE__ */ jsxs(
14887
15199
  "button",
14888
15200
  {
14889
15201
  type: "button",
14890
15202
  "data-select-all-row": true,
15203
+ id: focusedValue === "__select_all__" ? activeOptionId : void 0,
14891
15204
  "data-select-focused": focusedValue === "__select_all__" ? "true" : void 0,
14892
15205
  "data-select-active": focusedValue === "__select_all__" ? "true" : void 0,
14893
15206
  className: cn(
@@ -14929,6 +15242,7 @@ function ItemList({
14929
15242
  type: "button",
14930
15243
  "data-select-row": true,
14931
15244
  "data-index": idx,
15245
+ id: groupFocused ? activeOptionId : void 0,
14932
15246
  role: "option",
14933
15247
  "aria-selected": groupState === true,
14934
15248
  disabled: groupDisabled,
@@ -15002,6 +15316,7 @@ function ItemList({
15002
15316
  type: "button",
15003
15317
  "data-select-row": true,
15004
15318
  "data-index": idx,
15319
+ id: focusedValue === o.value ? activeOptionId : void 0,
15005
15320
  disabled: o.disabled,
15006
15321
  role: "option",
15007
15322
  "aria-selected": isSelected,
@@ -15086,6 +15401,22 @@ var cellValue = (col, row) => {
15086
15401
  return col.format ? col.format(raw, row) : raw;
15087
15402
  };
15088
15403
  var DEFAULT_COLUMN_WIDTH = 120;
15404
+ var LOCKED_BG = "var(--cmp-table-body-disabled-bg)";
15405
+ var LOCKED_CONTENT = "var(--cmp-table-body-disabled-content)";
15406
+ var DRAG_BG = "var(--cmp-table-dragSelectable-bg-color)";
15407
+ var DRAG_EDGE_W = "var(--cmp-table-dragSelectable-border-width)";
15408
+ var DRAG_EDGE_NEG_W = `calc(-1 * ${DRAG_EDGE_W})`;
15409
+ var DRAG_EDGE_C = "var(--cmp-table-dragSelectable-border-color)";
15410
+ var CONTEXT_MENU_VIEWPORT_PADDING = 12;
15411
+ var CONTEXT_MENU_CURSOR_GAP = 2;
15412
+ var CONTEXT_MENU_ARM_FALLBACK_MS = 500;
15413
+ var CONTEXT_MENU_ITEM_CLASS = cn(
15414
+ "flex min-h-[28px] cursor-pointer select-none items-center gap-[8px] rounded-[2px] px-[12px] py-[4px] text-[12px] leading-[20px] outline-none",
15415
+ "text-[color:var(--sys-color-fg-secondary)]",
15416
+ "data-[disabled]:cursor-not-allowed data-[disabled]:text-[color:var(--cmp-button-text-disabled)]",
15417
+ "data-[highlighted]:bg-[var(--sys-color-bg-accent)] data-[highlighted]:text-[color:var(--sys-color-fg-inverse)]"
15418
+ );
15419
+ var ROW_INTERACTIVE_SELECTOR = 'button, a, input, select, textarea, label, [role="button"], [role="checkbox"], [contenteditable="true"]';
15089
15420
  var colWidthFromDef = (c) => {
15090
15421
  if (c.autoWidth) return 0;
15091
15422
  if (c.width == null) return DEFAULT_COLUMN_WIDTH;
@@ -15098,6 +15429,9 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
15098
15429
  rows = [],
15099
15430
  rowKey = "id",
15100
15431
  selectable = false,
15432
+ dragSelectable = false,
15433
+ contextMenuItems,
15434
+ onContextMenuItemClick,
15101
15435
  isRowSelectable,
15102
15436
  selected = [],
15103
15437
  onSelectedChange,
@@ -15213,6 +15547,10 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
15213
15547
  (row) => isRowSelectable ? isRowSelectable(row) : true,
15214
15548
  [isRowSelectable]
15215
15549
  );
15550
+ const dragSelectOn = dragSelectable && !selectable;
15551
+ const portalContainer = usePortalContainer();
15552
+ const [dragPreviewKeys, setDragPreviewKeys] = useState(null);
15553
+ const dragRef = useRef(null);
15216
15554
  const getIsAllChecked = useCallback(
15217
15555
  (rws) => {
15218
15556
  const targets = rws.filter(canSelectRow);
@@ -15554,6 +15892,76 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
15554
15892
  onSelectedChange?.(selected.filter((r) => r[rowKey] !== row[rowKey]));
15555
15893
  else onSelectedChange?.([...selected, row]);
15556
15894
  };
15895
+ const isViewSelected = (row) => row != null && (dragPreviewKeys ?? selectedKeys).has(row[rowKey]);
15896
+ const dragRangeRows = (from, to) => {
15897
+ const [a, b] = from <= to ? [from, to] : [to, from];
15898
+ return rows.slice(a, b + 1).filter(canSelectRow);
15899
+ };
15900
+ const dragPreviewOf = (base, anchor, to) => /* @__PURE__ */ new Set([...base, ...dragRangeRows(anchor, to).map((r) => r[rowKey])]);
15901
+ const startDragSelect = (index, event) => {
15902
+ if (event.button !== 0) return;
15903
+ const target = event.target;
15904
+ if (target?.closest?.(ROW_INTERACTIVE_SELECTOR)) return;
15905
+ event.preventDefault();
15906
+ const baseRows = event.ctrlKey || event.metaKey ? selected : [];
15907
+ const baseKeys = new Set(baseRows.map((r) => r[rowKey]));
15908
+ dragRef.current = { anchor: index, last: index, baseKeys, baseRows };
15909
+ setDragPreviewKeys(dragPreviewOf(baseKeys, index, index));
15910
+ };
15911
+ const extendDragSelect = (index) => {
15912
+ const d = dragRef.current;
15913
+ if (!d || d.last === index) return;
15914
+ d.last = index;
15915
+ setDragPreviewKeys(dragPreviewOf(d.baseKeys, d.anchor, index));
15916
+ };
15917
+ const finishDragSelectRef = useRef(() => {
15918
+ });
15919
+ finishDragSelectRef.current = () => {
15920
+ const d = dragRef.current;
15921
+ if (!d) return;
15922
+ dragRef.current = null;
15923
+ setDragPreviewKeys(null);
15924
+ const add = dragRangeRows(d.anchor, d.last).filter((r) => !d.baseKeys.has(r[rowKey]));
15925
+ onSelectedChange?.([...d.baseRows, ...add]);
15926
+ };
15927
+ useEffect(() => {
15928
+ if (!dragSelectOn) return;
15929
+ const onUp = () => finishDragSelectRef.current();
15930
+ window.addEventListener("mouseup", onUp);
15931
+ return () => {
15932
+ window.removeEventListener("mouseup", onUp);
15933
+ dragRef.current = null;
15934
+ };
15935
+ }, [dragSelectOn]);
15936
+ const contextMenuOn = dragSelectOn && (contextMenuItems?.length ?? 0) > 0;
15937
+ const [contextMenu, setContextMenu] = useState(null);
15938
+ const contextMenuOpen = contextMenu?.open === true;
15939
+ const [contextMenuArmed, setContextMenuArmed] = useState(false);
15940
+ useEffect(() => {
15941
+ if (!contextMenuOpen || contextMenuArmed) return;
15942
+ const arm = () => setContextMenuArmed(true);
15943
+ window.addEventListener("pointerup", arm, { once: true, capture: true });
15944
+ const timer = window.setTimeout(arm, CONTEXT_MENU_ARM_FALLBACK_MS);
15945
+ return () => {
15946
+ window.removeEventListener("pointerup", arm, { capture: true });
15947
+ window.clearTimeout(timer);
15948
+ };
15949
+ }, [contextMenuOpen, contextMenuArmed]);
15950
+ useEffect(() => {
15951
+ if (!contextMenuOpen) return;
15952
+ const close = () => setContextMenu((m) => m == null ? null : { ...m, open: false });
15953
+ window.addEventListener("scroll", close, { capture: true, passive: true });
15954
+ return () => window.removeEventListener("scroll", close, { capture: true });
15955
+ }, [contextMenuOpen]);
15956
+ const openContextMenu = (row, event) => {
15957
+ if (!canSelectRow(row)) return;
15958
+ event.preventDefault();
15959
+ const alreadySelected = selectedKeys.has(row[rowKey]);
15960
+ const rows2 = alreadySelected ? selected : [row];
15961
+ if (!alreadySelected) onSelectedChange?.(rows2);
15962
+ setContextMenuArmed(false);
15963
+ setContextMenu({ x: event.clientX, y: event.clientY, rows: rows2, open: true });
15964
+ };
15557
15965
  const radiusClass = radius === "full" ? "rounded-none" : radius === "useTop" ? "rounded-b-[var(--cmp-table-radius)] rounded-t-none" : "rounded-[var(--cmp-table-radius)]";
15558
15966
  const cellPadY = innerDense ? "var(--cmp-table-body-paddingY-dense)" : "var(--cmp-table-body-paddingY-default)";
15559
15967
  const cellPadXOf = (col) => col.contentType === "control" ? "var(--cmp-table-body-paddingX-default)" : "var(--cmp-table-body-paddingX-wide)";
@@ -15576,14 +15984,13 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
15576
15984
  zIndex: 6
15577
15985
  };
15578
15986
  };
15579
- const stickyShadowClass = (i) => {
15987
+ const stickyShadowValue = (i) => {
15580
15988
  const { isLeft, isRight } = stickyInfo(i);
15581
15989
  const isLeftEdge = isLeft && i === stickyLeft - 1;
15582
15990
  const isRightEdge = isRight && i === visibleCols.length - stickyRight;
15583
- return cn(
15584
- isLeftEdge && scrolledLeft && "shadow-[5px_0_8px_0_rgba(34,34,34,0.1)]",
15585
- isRightEdge && scrolledRight && "shadow-[-5px_0_8px_0_rgba(34,34,34,0.1)]"
15586
- );
15991
+ if (isLeftEdge && scrolledLeft) return "5px 0 8px 0 rgba(34,34,34,0.1)";
15992
+ if (isRightEdge && scrolledRight) return "-5px 0 8px 0 rgba(34,34,34,0.1)";
15993
+ return null;
15587
15994
  };
15588
15995
  const headerResizeHitArea = (i, key) => {
15589
15996
  const col = visibleCols[i];
@@ -15777,10 +16184,14 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
15777
16184
  headerGroupInfo && i === visibleCols.length - 1 && "border-r-0",
15778
16185
  "relative bg-[var(--cmp-table-header-bg)] px-[16px] text-[12px] font-medium leading-[0] text-[color:var(--sys-color-fg-primary)]",
15779
16186
  stickyInfo(i).isSticky && "z-[6]",
15780
- stickyShadowClass(i),
15781
16187
  col.thClass
15782
16188
  ),
15783
- style: { textAlign: col.align ?? "left", ...cellStyle(i), ...col.thStyle },
16189
+ style: {
16190
+ textAlign: col.align ?? "left",
16191
+ boxShadow: stickyShadowValue(i) ?? void 0,
16192
+ ...cellStyle(i),
16193
+ ...col.thStyle
16194
+ },
15784
16195
  "aria-sort": isSortable ? sortDir === "asc" ? "ascending" : sortDir === "desc" ? "descending" : "none" : void 0,
15785
16196
  children: [
15786
16197
  /* @__PURE__ */ jsx(
@@ -15892,17 +16303,27 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
15892
16303
  /* @__PURE__ */ jsxs("tbody", { children: [
15893
16304
  virtualScroll && topSpacer > 0 && /* @__PURE__ */ jsx("tr", { "aria-hidden": true, style: { height: topSpacer }, children: /* @__PURE__ */ jsx("td", { colSpan: totalColSpan, className: "p-0" }) }),
15894
16305
  rowCount === 0 ? null : bodyRows.map((row, ri) => {
15895
- const isSel = selectedKeys.has(row[rowKey]);
16306
+ const rowIndex = rowOffset + ri;
16307
+ const isSel = isViewSelected(row);
16308
+ const dragSel = dragSelectOn && isSel;
16309
+ const dragTop = dragSel && !isViewSelected(rows[rowIndex - 1]);
16310
+ const dragBottom = dragSel && !isViewSelected(rows[rowIndex + 1]);
16311
+ const rowLocked = (selectable || dragSelectable) && !canSelectRow(row);
15896
16312
  const rowBg = "bg-white";
16313
+ const rowHover = hoverable && !rowLocked;
15897
16314
  return /* @__PURE__ */ jsxs(
15898
16315
  "tr",
15899
16316
  {
15900
- "data-row-index": rowOffset + ri,
16317
+ "data-row-index": rowIndex,
15901
16318
  onClick: () => onRowClick?.(row),
16319
+ onMouseDown: dragSelectOn ? (event) => startDragSelect(rowIndex, event) : void 0,
16320
+ onMouseEnter: dragSelectOn ? () => extendDragSelect(rowIndex) : void 0,
16321
+ onContextMenu: contextMenuOn ? (event) => openContextMenu(row, event) : void 0,
15902
16322
  className: cn(
15903
16323
  "group/table-row",
15904
- hoverable && "hover:bg-[var(--color-grey-05)]",
15905
- onRowClick && "cursor-pointer"
16324
+ rowHover && "hover:bg-[var(--color-grey-05)]",
16325
+ onRowClick && "cursor-pointer",
16326
+ dragSelectOn && "select-none"
15906
16327
  ),
15907
16328
  style: { height: virtualScroll ? effectiveRowHeight : rowH },
15908
16329
  children: [
@@ -15913,13 +16334,15 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
15913
16334
  // 원본 .td--selected: 48px 고정폭, 항상 left sticky, 체크박스 중앙정렬
15914
16335
  "sticky left-0 z-[2] border-b border-solid border-[color:var(--cmp-table-border-color)] align-middle",
15915
16336
  rowBg,
15916
- hoverable && "group-hover/table-row:bg-[var(--color-grey-05)]",
16337
+ rowHover && "group-hover/table-row:bg-[var(--color-grey-05)]",
15917
16338
  stickyLeft === 0 && scrolledLeft && "shadow-[5px_0_8px_0_rgba(34,34,34,0.1)]"
15918
16339
  ),
15919
16340
  style: {
15920
16341
  width: SELECTABLE_COLUMN_WIDTH,
15921
16342
  minWidth: SELECTABLE_COLUMN_WIDTH,
15922
- maxWidth: SELECTABLE_COLUMN_WIDTH
16343
+ maxWidth: SELECTABLE_COLUMN_WIDTH,
16344
+ // 선택 열도 행의 일부다 — 여기만 희지 않으면 회색 줄이 끊긴다
16345
+ background: rowLocked ? LOCKED_BG : void 0
15923
16346
  },
15924
16347
  onClick: (e) => e.stopPropagation(),
15925
16348
  onClickCapture: (e) => {
@@ -15942,17 +16365,29 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
15942
16365
  // 셀 배경은 흰색으로 채워 뒤 배경이 비치지 않게 하고, hover 시 행 배경(grey_05)을 따른다.
15943
16366
  "overflow-hidden text-ellipsis whitespace-nowrap border-b border-solid border-[color:var(--cmp-table-border-color)] text-[12px] leading-[20px] text-[color:var(--sys-color-fg-primary)]",
15944
16367
  rowBg,
15945
- hoverable && "group-hover/table-row:bg-[var(--color-grey-05)]",
15946
- stickyShadowClass(i),
16368
+ rowHover && "group-hover/table-row:bg-[var(--color-grey-05)]",
15947
16369
  typeof col.tdClass === "function" ? col.tdClass(row) : col.tdClass
15948
16370
  );
15949
16371
  const tdPadX = cellPadXOf(col);
16372
+ const dragEdges = dragSel ? [
16373
+ dragTop && `inset 0 ${DRAG_EDGE_W} 0 0 ${DRAG_EDGE_C}`,
16374
+ dragBottom && `inset 0 ${DRAG_EDGE_NEG_W} 0 0 ${DRAG_EDGE_C}`,
16375
+ i === 0 && `inset ${DRAG_EDGE_W} 0 0 0 ${DRAG_EDGE_C}`,
16376
+ i === visibleCols.length - 1 && `inset ${DRAG_EDGE_NEG_W} 0 0 0 ${DRAG_EDGE_C}`
16377
+ ].filter(Boolean) : [];
16378
+ const shadows = [...dragEdges, stickyShadowValue(i)].filter(Boolean);
15950
16379
  const tdStyle = {
15951
16380
  paddingLeft: tdPadX,
15952
16381
  paddingRight: tdPadX,
15953
16382
  paddingTop: cellPadY,
15954
16383
  paddingBottom: cellPadY,
15955
16384
  textAlign: col.align ?? "left",
16385
+ // 인라인이라 hover 배경보다 세다 — 고른 행은 hover 로 흐려지지 않는다.
16386
+ background: dragSel ? DRAG_BG : rowLocked ? LOCKED_BG : void 0,
16387
+ // 클래스의 기본 글자색을 덮는다. 셀이 자기 색을 정한 내용(SIcon 의
16388
+ // color, STag 등)까지는 닿지 않는다 — 그건 소비 앱 몫이다.
16389
+ color: rowLocked ? LOCKED_CONTENT : void 0,
16390
+ boxShadow: shadows.length > 0 ? shadows.join(", ") : void 0,
15956
16391
  ...cellStyle(i)
15957
16392
  };
15958
16393
  if (col.renderCell) {
@@ -16040,6 +16475,59 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
16040
16475
  ] })
16041
16476
  ]
16042
16477
  }
16478
+ ),
16479
+ contextMenuOn && typeof document !== "undefined" && createPortal(
16480
+ /* @__PURE__ */ jsxs(
16481
+ RDropdown3.Root,
16482
+ {
16483
+ modal: false,
16484
+ open: contextMenuOpen,
16485
+ onOpenChange: (open) => {
16486
+ if (!open) setContextMenu((m) => m == null ? null : { ...m, open: false });
16487
+ },
16488
+ children: [
16489
+ /* @__PURE__ */ jsx(RDropdown3.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(
16490
+ "span",
16491
+ {
16492
+ "aria-hidden": true,
16493
+ className: "pointer-events-none fixed block h-0 w-0",
16494
+ style: { left: contextMenu?.x ?? 0, top: contextMenu?.y ?? 0 }
16495
+ }
16496
+ ) }),
16497
+ /* @__PURE__ */ jsx(
16498
+ RDropdown3.Content,
16499
+ {
16500
+ align: "start",
16501
+ side: "bottom",
16502
+ sideOffset: CONTEXT_MENU_CURSOR_GAP,
16503
+ alignOffset: CONTEXT_MENU_CURSOR_GAP,
16504
+ collisionPadding: CONTEXT_MENU_VIEWPORT_PADDING,
16505
+ style: contextMenuArmed ? void 0 : { pointerEvents: "none" },
16506
+ className: cn(
16507
+ "z-50 overflow-hidden rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)] shadow-normal-sm",
16508
+ "max-w-[var(--radix-dropdown-menu-content-available-width)]",
16509
+ FLOATING_SLIDE_ANIM
16510
+ ),
16511
+ children: contextMenuItems?.map((item4) => /* @__PURE__ */ jsxs(
16512
+ RDropdown3.Item,
16513
+ {
16514
+ disabled: item4.disabled,
16515
+ onSelect: () => onContextMenuItemClick?.(item4.value, contextMenu?.rows ?? []),
16516
+ className: CONTEXT_MENU_ITEM_CLASS,
16517
+ children: [
16518
+ item4.icon && /* @__PURE__ */ jsx(SIcon, { name: item4.icon, size: 12 }),
16519
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 break-words", children: item4.label })
16520
+ ]
16521
+ },
16522
+ item4.value
16523
+ ))
16524
+ }
16525
+ )
16526
+ ]
16527
+ },
16528
+ contextMenu == null ? "closed" : `${contextMenu.x},${contextMenu.y}`
16529
+ ),
16530
+ portalContainer ?? document.body
16043
16531
  )
16044
16532
  ]
16045
16533
  }
@@ -17558,11 +18046,11 @@ function RangeCalendar({
17558
18046
  const goPrevYear = () => setBase(y - 1, m);
17559
18047
  const goNextYear = () => setBase(y + 1, m);
17560
18048
  const goPrevMonth = () => {
17561
- const n = calcYearMonth(y, m, "prev");
18049
+ const n = calcYearMonth(y, m, "prev", 2);
17562
18050
  setBase(n.year, n.month);
17563
18051
  };
17564
18052
  const goNextMonth = () => {
17565
- const n = calcYearMonth(y, m, "next");
18053
+ const n = calcYearMonth(y, m, "next", 2);
17566
18054
  setBase(n.year, n.month);
17567
18055
  };
17568
18056
  const goToday = () => {
@@ -18907,20 +19395,24 @@ function ChartTooltip({
18907
19395
  },
18908
19396
  children: [
18909
19397
  /* @__PURE__ */ jsx("span", { className: "typo-body-md-bold text-(--cmp-chart-chartTooltip-title-color)", children: title }),
18910
- items.map((item4, index) => (
18911
- // TODO: 토큰 생성되면 gap 을 `--cmp-chart-chartTooltipItem-gap` 으로 교체
18912
- /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-sd-8", children: [
18913
- /* @__PURE__ */ jsx(
18914
- "span",
18915
- {
18916
- "aria-hidden": true,
18917
- className: "shrink-0 rounded-full",
18918
- style: { width: DOT_SIZE2, height: DOT_SIZE2, background: item4.color }
18919
- }
18920
- ),
18921
- /* @__PURE__ */ jsx("span", { className: "typo-body-sm-default text-(--sys-color-fg-primary)", children: item4.label }),
18922
- /* @__PURE__ */ jsx("span", { className: "typo-body-sm-bold ml-auto text-(--sys-color-fg-primary)", children: item4.value })
18923
- ] }, `${item4.label}-${index}`)
19398
+ items.map((item4, index) => /* @__PURE__ */ jsxs(
19399
+ "span",
19400
+ {
19401
+ className: "flex items-center gap-(--cmp-chart-chartTooltipItem-gap)",
19402
+ children: [
19403
+ /* @__PURE__ */ jsx(
19404
+ "span",
19405
+ {
19406
+ "aria-hidden": true,
19407
+ className: "shrink-0 rounded-full",
19408
+ style: { width: DOT_SIZE2, height: DOT_SIZE2, background: item4.color }
19409
+ }
19410
+ ),
19411
+ /* @__PURE__ */ jsx("span", { className: "typo-body-sm-default text-(--cmp-chart-chartTooltipItem-label-color)", children: item4.label }),
19412
+ /* @__PURE__ */ jsx("span", { className: "typo-body-sm-bold ml-auto text-(--cmp-chart-chartTooltipItem-dataValue-color)", children: item4.value })
19413
+ ]
19414
+ },
19415
+ `${item4.label}-${index}`
18924
19416
  ))
18925
19417
  ]
18926
19418
  }
@@ -20774,7 +21266,7 @@ var PaletteItem = ({
20774
21266
  className,
20775
21267
  onSelect,
20776
21268
  children
20777
- }) => asMenu ? /* @__PURE__ */ jsx(RDropdown2.Item, { title: label, "aria-label": label, className, onSelect, children }) : /* @__PURE__ */ jsx("button", { type: "button", title: label, "aria-label": label, className, onClick: onSelect, children });
21269
+ }) => asMenu ? /* @__PURE__ */ jsx(RDropdown3.Item, { title: label, "aria-label": label, className, onSelect, children }) : /* @__PURE__ */ jsx("button", { type: "button", title: label, "aria-label": label, className, onClick: onSelect, children });
20778
21270
  var ColorPalette = ({
20779
21271
  colors,
20780
21272
  columns,
@@ -20906,7 +21398,7 @@ var TableMenuItem = ({
20906
21398
  disabled,
20907
21399
  onSelect
20908
21400
  }) => /* @__PURE__ */ jsx(
20909
- RDropdown2.Item,
21401
+ RDropdown3.Item,
20910
21402
  {
20911
21403
  className: cn(menuItemClass, menuItemDisabledClass),
20912
21404
  disabled,
@@ -21073,8 +21565,8 @@ function EditorToolbarBar({
21073
21565
  const node = (item4) => {
21074
21566
  switch (item4) {
21075
21567
  case "heading":
21076
- return /* @__PURE__ */ jsxs(RDropdown2.Root, { modal: !insideModal, children: [
21077
- /* @__PURE__ */ jsx(RDropdown2.Trigger, { asChild: true, disabled: off, children: /* @__PURE__ */ jsxs(
21568
+ return /* @__PURE__ */ jsxs(RDropdown3.Root, { modal: !insideModal, children: [
21569
+ /* @__PURE__ */ jsx(RDropdown3.Trigger, { asChild: true, disabled: off, children: /* @__PURE__ */ jsxs(
21078
21570
  ToolbarButton,
21079
21571
  {
21080
21572
  label: "\uC81C\uBAA9 \uB2E8\uACC4",
@@ -21087,9 +21579,9 @@ function EditorToolbarBar({
21087
21579
  ]
21088
21580
  }
21089
21581
  ) }),
21090
- /* @__PURE__ */ jsx(RDropdown2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(RDropdown2.Content, { sideOffset: 4, align: "start", className: menuClass, children: [
21582
+ /* @__PURE__ */ jsx(RDropdown3.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(RDropdown3.Content, { sideOffset: 4, align: "start", className: menuClass, children: [
21091
21583
  /* @__PURE__ */ jsx(
21092
- RDropdown2.Item,
21584
+ RDropdown3.Item,
21093
21585
  {
21094
21586
  className: menuItemClass,
21095
21587
  onSelect: () => chain()?.setParagraph().run(),
@@ -21097,7 +21589,7 @@ function EditorToolbarBar({
21097
21589
  }
21098
21590
  ),
21099
21591
  SEDITOR_HEADING_LEVELS.map((level) => /* @__PURE__ */ jsx(
21100
- RDropdown2.Item,
21592
+ RDropdown3.Item,
21101
21593
  {
21102
21594
  className: menuItemClass,
21103
21595
  onSelect: () => chain()?.setHeading({ level }).run(),
@@ -21108,13 +21600,13 @@ function EditorToolbarBar({
21108
21600
  ] }) })
21109
21601
  ] }, item4);
21110
21602
  case "fontSize":
21111
- return /* @__PURE__ */ jsxs(RDropdown2.Root, { modal: !insideModal, children: [
21112
- /* @__PURE__ */ jsx(RDropdown2.Trigger, { asChild: true, disabled: off, children: /* @__PURE__ */ jsxs(ToolbarButton, { label: "\uAE00\uC790 \uD06C\uAE30", disabled: off, className: "px-[6px]", children: [
21603
+ return /* @__PURE__ */ jsxs(RDropdown3.Root, { modal: !insideModal, children: [
21604
+ /* @__PURE__ */ jsx(RDropdown3.Trigger, { asChild: true, disabled: off, children: /* @__PURE__ */ jsxs(ToolbarButton, { label: "\uAE00\uC790 \uD06C\uAE30", disabled: off, className: "px-[6px]", children: [
21113
21605
  /* @__PURE__ */ jsx("span", { className: "text-[12px] leading-[20px]", children: activeFontSize ?? FONT_SIZE_DEFAULT_LABEL }),
21114
21606
  /* @__PURE__ */ jsx(SIcon, { name: "caretDown", size: 12 })
21115
21607
  ] }) }),
21116
- /* @__PURE__ */ jsx(RDropdown2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(
21117
- RDropdown2.Content,
21608
+ /* @__PURE__ */ jsx(RDropdown3.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(
21609
+ RDropdown3.Content,
21118
21610
  {
21119
21611
  sideOffset: 4,
21120
21612
  align: "start",
@@ -21122,7 +21614,7 @@ function EditorToolbarBar({
21122
21614
  style: { maxHeight: FONT_SIZE_MENU_MAX_HEIGHT },
21123
21615
  children: [
21124
21616
  /* @__PURE__ */ jsx(
21125
- RDropdown2.Item,
21617
+ RDropdown3.Item,
21126
21618
  {
21127
21619
  className: cn(menuItemClass, activeFontSize === null && menuItemSelectedClass),
21128
21620
  title: `${FONT_SIZE_DEFAULT_LABEL} (\uBCF8\uBB38 ${SEDITOR_DEFAULT_FONT_SIZE}px)`,
@@ -21131,7 +21623,7 @@ function EditorToolbarBar({
21131
21623
  }
21132
21624
  ),
21133
21625
  SEDITOR_FONT_SIZES.map((size) => /* @__PURE__ */ jsx(
21134
- RDropdown2.Item,
21626
+ RDropdown3.Item,
21135
21627
  {
21136
21628
  ref: activeFontSize === size ? (el) => {
21137
21629
  el?.scrollIntoView({ block: "nearest" });
@@ -21223,9 +21715,9 @@ function EditorToolbarBar({
21223
21715
  },
21224
21716
  item4
21225
21717
  );
21226
- return /* @__PURE__ */ jsxs(RDropdown2.Root, { modal: !insideModal, children: [
21227
- /* @__PURE__ */ jsx(RDropdown2.Trigger, { asChild: true, disabled: off, children: /* @__PURE__ */ jsx(ToolbarButton, { label: "\uAE00\uC790\uC0C9", disabled: off, children: /* @__PURE__ */ jsx(ColorIndicator, { color: off ? "currentColor" : activeColor, children: /* @__PURE__ */ jsx(IconTextColor, { size: ICON_SIZE }) }) }) }),
21228
- /* @__PURE__ */ jsx(RDropdown2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(RDropdown2.Content, { sideOffset: 4, align: "start", className: menuClass, children: /* @__PURE__ */ jsx(
21718
+ return /* @__PURE__ */ jsxs(RDropdown3.Root, { modal: !insideModal, children: [
21719
+ /* @__PURE__ */ jsx(RDropdown3.Trigger, { asChild: true, disabled: off, children: /* @__PURE__ */ jsx(ToolbarButton, { label: "\uAE00\uC790\uC0C9", disabled: off, children: /* @__PURE__ */ jsx(ColorIndicator, { color: off ? "currentColor" : activeColor, children: /* @__PURE__ */ jsx(IconTextColor, { size: ICON_SIZE }) }) }) }),
21720
+ /* @__PURE__ */ jsx(RDropdown3.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(RDropdown3.Content, { sideOffset: 4, align: "start", className: menuClass, children: /* @__PURE__ */ jsx(
21229
21721
  ColorPalette,
21230
21722
  {
21231
21723
  asMenu: true,
@@ -21331,14 +21823,14 @@ function EditorToolbarBar({
21331
21823
  case "list": {
21332
21824
  const ListIcon = state2.orderedList ? IconOrderedList : state2.taskList ? IconTaskList : IconBulletList;
21333
21825
  const listActive = state2.bulletList || state2.orderedList || state2.taskList;
21334
- return /* @__PURE__ */ jsxs(RDropdown2.Root, { modal: !insideModal, children: [
21335
- /* @__PURE__ */ jsx(RDropdown2.Trigger, { asChild: true, disabled: off, children: /* @__PURE__ */ jsxs(ToolbarButton, { label: "\uBAA9\uB85D", active: listActive, disabled: off, className: "px-[4px]", children: [
21826
+ return /* @__PURE__ */ jsxs(RDropdown3.Root, { modal: !insideModal, children: [
21827
+ /* @__PURE__ */ jsx(RDropdown3.Trigger, { asChild: true, disabled: off, children: /* @__PURE__ */ jsxs(ToolbarButton, { label: "\uBAA9\uB85D", active: listActive, disabled: off, className: "px-[4px]", children: [
21336
21828
  /* @__PURE__ */ jsx(ListIcon, { size: ICON_SIZE }),
21337
21829
  /* @__PURE__ */ jsx(SIcon, { name: "caretDown", size: CARET_SIZE })
21338
21830
  ] }) }),
21339
- /* @__PURE__ */ jsx(RDropdown2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(RDropdown2.Content, { sideOffset: 4, align: "start", className: menuClass, children: [
21831
+ /* @__PURE__ */ jsx(RDropdown3.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(RDropdown3.Content, { sideOffset: 4, align: "start", className: menuClass, children: [
21340
21832
  /* @__PURE__ */ jsxs(
21341
- RDropdown2.Item,
21833
+ RDropdown3.Item,
21342
21834
  {
21343
21835
  className: menuItemClass,
21344
21836
  onSelect: () => chain()?.toggleBulletList().run(),
@@ -21349,7 +21841,7 @@ function EditorToolbarBar({
21349
21841
  }
21350
21842
  ),
21351
21843
  /* @__PURE__ */ jsxs(
21352
- RDropdown2.Item,
21844
+ RDropdown3.Item,
21353
21845
  {
21354
21846
  className: menuItemClass,
21355
21847
  onSelect: () => chain()?.toggleOrderedList().run(),
@@ -21360,7 +21852,7 @@ function EditorToolbarBar({
21360
21852
  }
21361
21853
  ),
21362
21854
  /* @__PURE__ */ jsxs(
21363
- RDropdown2.Item,
21855
+ RDropdown3.Item,
21364
21856
  {
21365
21857
  className: menuItemClass,
21366
21858
  onSelect: () => chain()?.toggleTaskList().run(),
@@ -21464,17 +21956,17 @@ function EditorToolbarBar({
21464
21956
  );
21465
21957
  case "table":
21466
21958
  return /* @__PURE__ */ jsxs(
21467
- RDropdown2.Root,
21959
+ RDropdown3.Root,
21468
21960
  {
21469
21961
  open: tableOpen,
21470
21962
  onOpenChange: setTableOpen,
21471
21963
  modal: !insideModal,
21472
21964
  children: [
21473
- /* @__PURE__ */ jsx(RDropdown2.Trigger, { asChild: true, disabled: off, children: /* @__PURE__ */ jsxs(ToolbarButton, { label: "\uD45C", active: state2.inTable, disabled: off, className: "px-[6px]", children: [
21965
+ /* @__PURE__ */ jsx(RDropdown3.Trigger, { asChild: true, disabled: off, children: /* @__PURE__ */ jsxs(ToolbarButton, { label: "\uD45C", active: state2.inTable, disabled: off, className: "px-[6px]", children: [
21474
21966
  /* @__PURE__ */ jsx(IconTable, { size: ICON_SIZE }),
21475
21967
  /* @__PURE__ */ jsx(SIcon, { name: "caretDown", size: CARET_SIZE })
21476
21968
  ] }) }),
21477
- /* @__PURE__ */ jsx(RDropdown2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(RDropdown2.Content, { sideOffset: 4, align: "start", className: menuClass, children: [
21969
+ /* @__PURE__ */ jsx(RDropdown3.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(RDropdown3.Content, { sideOffset: 4, align: "start", className: menuClass, children: [
21478
21970
  !state2.inTable && /* @__PURE__ */ jsxs(Fragment, { children: [
21479
21971
  /* @__PURE__ */ jsx(
21480
21972
  TableSizePicker,
@@ -21486,7 +21978,7 @@ function EditorToolbarBar({
21486
21978
  }
21487
21979
  }
21488
21980
  ),
21489
- /* @__PURE__ */ jsx(RDropdown2.Separator, { className: menuSeparatorClass })
21981
+ /* @__PURE__ */ jsx(RDropdown3.Separator, { className: menuSeparatorClass })
21490
21982
  ] }),
21491
21983
  /* @__PURE__ */ jsx(
21492
21984
  TableMenuItem,
@@ -21520,7 +22012,7 @@ function EditorToolbarBar({
21520
22012
  onSelect: () => chain()?.addColumnAfter().run()
21521
22013
  }
21522
22014
  ),
21523
- /* @__PURE__ */ jsx(RDropdown2.Separator, { className: menuSeparatorClass }),
22015
+ /* @__PURE__ */ jsx(RDropdown3.Separator, { className: menuSeparatorClass }),
21524
22016
  /* @__PURE__ */ jsx(
21525
22017
  TableMenuItem,
21526
22018
  {
@@ -21553,7 +22045,7 @@ function EditorToolbarBar({
21553
22045
  onSelect: () => chain()?.toggleHeaderColumn().run()
21554
22046
  }
21555
22047
  ),
21556
- /* @__PURE__ */ jsx(RDropdown2.Separator, { className: menuSeparatorClass }),
22048
+ /* @__PURE__ */ jsx(RDropdown3.Separator, { className: menuSeparatorClass }),
21557
22049
  /* @__PURE__ */ jsx(
21558
22050
  TableMenuItem,
21559
22051
  {
@@ -24027,6 +24519,8 @@ var SChipInput = /* @__PURE__ */ forwardRef(function SChipInput2({
24027
24519
  }, ref) {
24028
24520
  const autoId = useId();
24029
24521
  const resolvedName = name ?? autoId;
24522
+ const listboxId = `${autoId}-listbox`;
24523
+ const activeOptionId = `${autoId}-active-option`;
24030
24524
  const [inputValue, setInputValue] = useState("");
24031
24525
  const [focused, setFocused] = useState(false);
24032
24526
  const [hovered, setHovered] = useState(false);
@@ -24249,6 +24743,11 @@ var SChipInput = /* @__PURE__ */ forwardRef(function SChipInput2({
24249
24743
  ref: inputRef,
24250
24744
  name: resolvedName,
24251
24745
  size: 1,
24746
+ role: "combobox",
24747
+ "aria-expanded": showDropdown,
24748
+ "aria-controls": showDropdown ? listboxId : void 0,
24749
+ "aria-activedescendant": showDropdown && activeIndex >= 0 ? activeOptionId : void 0,
24750
+ "aria-autocomplete": "list",
24252
24751
  className: cn(
24253
24752
  "s-chip-input__input col-start-1 row-start-1 w-full border-0 bg-transparent p-0 font-normal text-(--cmp-chip-content-focus) outline-none placeholder:text-(--cmp-chipInput-text-placeholder) disabled:cursor-not-allowed",
24254
24753
  AUTOFILL_RESET_CLASS,
@@ -24362,6 +24861,7 @@ var SChipInput = /* @__PURE__ */ forwardRef(function SChipInput2({
24362
24861
  children: /* @__PURE__ */ jsxs(
24363
24862
  "div",
24364
24863
  {
24864
+ id: listboxId,
24365
24865
  role: "listbox",
24366
24866
  className: "s-chip-input__suggestions flex w-full flex-col outline-none",
24367
24867
  onMouseDown: (e) => e.preventDefault(),
@@ -24373,6 +24873,7 @@ var SChipInput = /* @__PURE__ */ forwardRef(function SChipInput2({
24373
24873
  return /* @__PURE__ */ jsx(
24374
24874
  "div",
24375
24875
  {
24876
+ id: active ? activeOptionId : void 0,
24376
24877
  role: "option",
24377
24878
  "aria-selected": selected || active,
24378
24879
  className: "rounded-full",
@@ -24391,6 +24892,7 @@ var SChipInput = /* @__PURE__ */ forwardRef(function SChipInput2({
24391
24892
  return /* @__PURE__ */ jsxs(
24392
24893
  "div",
24393
24894
  {
24895
+ id: active ? activeOptionId : void 0,
24394
24896
  role: "option",
24395
24897
  "aria-selected": selected || active,
24396
24898
  className: cn(