@morze/ui 0.2.5 → 0.2.7

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/README.md CHANGED
@@ -449,7 +449,12 @@ What it does:
449
449
  and the floating bar can escalate to "all N matching" (in that mode a bulk
450
450
  action must travel with the query, not with a list of ids).
451
451
  - **Columns** — visibility, order (drag and drop plus arrows for the keyboard)
452
- and pinning; all of it saved to `localStorage` under `persistKey`.
452
+ and pinning; all of it saved to `localStorage` under `persistKey`. The list
453
+ is grouped the way the table paints — pinned left, loose, pinned right — and
454
+ a move stays inside its group, so what you drag is where it lands. A column
455
+ whose header is a node rather than text is listed by position: “#3”.
456
+ `columnManager={false}` drops the button for a layout the host fixes or
457
+ drives itself; the layout props keep working without it.
453
458
  - **Expandable rows** and **inline cell editing** on double click, with
454
459
  optimistic saving and a rollback on failure.
455
460
  - **States** — skeletons on the first load, a thin progress line when refetching
package/dist/index.cjs CHANGED
@@ -160,8 +160,8 @@ var ArrowUpIcon = icon(/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 19V5m-7
160
160
  var ArrowDownIcon = icon(/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 5v14m7-7-7 7-7-7" }));
161
161
  var SortIcon = icon(
162
162
  /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
163
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m7 15 3 3 3-3", opacity: "0.9" }),
164
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m7 9 3-3 3 3", opacity: "0.9" })
163
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m8 10 4-4 4 4" }),
164
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m8 14 4 4 4-4" })
165
165
  ] })
166
166
  );
167
167
  var FilterIcon = icon(/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 5h16l-6.5 7.5V19l-3 2v-8.5L4 5Z" }));
@@ -181,7 +181,13 @@ var GripIcon = icon(
181
181
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "15", cy: "17", r: "1.4", fill: "currentColor" })
182
182
  ] })
183
183
  );
184
- var PinIcon = icon(/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 3 21 9l-4 1-4 4-1 5-6-6 5-1 4-4 1-4Z" }));
184
+ var PinIcon = icon(
185
+ /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
186
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 4h6v5l3 4v2H6v-2l3-4V4Z" }),
187
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 4h8" }),
188
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 15v5" })
189
+ ] })
190
+ );
185
191
  var EyeIcon = icon(
186
192
  /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
187
193
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z" }),
@@ -910,6 +916,9 @@ function Avatar({
910
916
  }
911
917
  );
912
918
  }
919
+ function AvatarGroup({ className, ...props }) {
920
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "avatar-group", role: "group", className: cn("mz-avatar-group", className), ...props });
921
+ }
913
922
  function AvatarImage({ className, ...props }) {
914
923
  return /* @__PURE__ */ jsxRuntime.jsx(
915
924
  radixUi.Avatar.Image,
@@ -2101,26 +2110,53 @@ function FilterChip({
2101
2110
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onClear, "aria-label": clearLabel, className: "mz-focusable", children: "\xD7" })
2102
2111
  ] });
2103
2112
  }
2113
+ function nameOf(column, declaredIndex) {
2114
+ if (column.label?.trim()) return column.label;
2115
+ if (typeof column.header === "string" && column.header.trim()) return column.header;
2116
+ return `#${declaredIndex + 1}`;
2117
+ }
2104
2118
  function ColumnManager({
2105
2119
  columns,
2106
2120
  layout,
2107
2121
  onToggleHidden,
2108
2122
  onSetPinned,
2109
- onMove,
2110
2123
  onMoveTo,
2111
2124
  onReset,
2112
2125
  labels: labelsProp
2113
2126
  }) {
2114
2127
  const labels = resolveLabels(labelsProp);
2115
2128
  const [dragging, setDragging] = React39__namespace.useState(null);
2116
- const byId = React39__namespace.useMemo(() => new Map(columns.map((c) => [c.id, c])), [columns]);
2117
- const ordered = layout.order.map((id) => byId.get(id)).filter((c) => Boolean(c));
2129
+ const [dropTarget, setDropTarget] = React39__namespace.useState(null);
2130
+ const entries = React39__namespace.useMemo(() => {
2131
+ const byId = new Map(columns.map((c, index) => [c.id, { column: c, declaredIndex: index }]));
2132
+ const ordered = layout.order.map((id) => byId.get(id)).filter((e) => Boolean(e));
2133
+ const side = (id) => layout.pinned[id];
2134
+ const groups = ["left", void 0, "right"];
2135
+ return groups.flatMap((group) => {
2136
+ const inGroup = ordered.filter((e) => side(e.column.id) === group);
2137
+ return inGroup.map((entry, indexInGroup) => ({
2138
+ ...entry,
2139
+ side: group,
2140
+ indexInGroup,
2141
+ groupSize: inGroup.length,
2142
+ previous: inGroup[indexInGroup - 1]?.column.id,
2143
+ next: inGroup[indexInGroup + 1]?.column.id,
2144
+ name: nameOf(entry.column, entry.declaredIndex)
2145
+ }));
2146
+ });
2147
+ }, [columns, layout]);
2148
+ const sideOf = (id) => layout.pinned[id];
2149
+ const canDrop = (targetId) => Boolean(dragging) && dragging !== targetId && sideOf(dragging) === sideOf(targetId);
2150
+ const endDrag = () => {
2151
+ setDragging(null);
2152
+ setDropTarget(null);
2153
+ };
2118
2154
  const hiddenCount = layout.hidden.length;
2119
2155
  return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { children: [
2120
2156
  /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "secondary", size: "sm", children: [
2121
2157
  /* @__PURE__ */ jsxRuntime.jsx(ColumnsIcon, {}),
2122
2158
  labels.columns,
2123
- hiddenCount > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mz-dt__count", children: ordered.length - hiddenCount }) : null
2159
+ hiddenCount > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mz-dt__count", children: entries.length - hiddenCount }) : null
2124
2160
  ] }) }),
2125
2161
  /* @__PURE__ */ jsxRuntime.jsxs(PopoverContent, { align: "end", className: "mz-dt__columns", children: [
2126
2162
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mz-dt__columns-head", children: [
@@ -2128,35 +2164,60 @@ function ColumnManager({
2128
2164
  /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "link", size: "xs", onClick: onReset, children: labels.reset })
2129
2165
  ] }),
2130
2166
  /* @__PURE__ */ jsxRuntime.jsx(Separator, {}),
2131
- /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "mz-dt__columns-list", children: ordered.map((column, index) => {
2167
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "mz-dt__columns-list", children: entries.map((entry) => {
2168
+ const column = entry.column;
2132
2169
  const hidden = layout.hidden.includes(column.id);
2133
- const pinned = layout.pinned[column.id];
2134
- const label = column.label ?? (typeof column.header === "string" ? column.header : column.id);
2170
+ const pinned = entry.side;
2171
+ const name = entry.name;
2172
+ const pinTitle = pinned === "left" ? labels.pinnedLeft : pinned === "right" ? labels.pinnedRight : labels.notPinned;
2135
2173
  return /* @__PURE__ */ jsxRuntime.jsxs(
2136
2174
  "li",
2137
2175
  {
2138
2176
  className: "mz-dt__columns-item",
2139
2177
  "data-dragging": dragging === column.id || void 0,
2178
+ "data-drop": dropTarget === column.id || void 0,
2179
+ "data-pinned": pinned,
2140
2180
  draggable: true,
2141
- onDragStart: () => setDragging(column.id),
2142
- onDragEnd: () => setDragging(null),
2143
- onDragOver: (event) => event.preventDefault(),
2144
- onDrop: () => {
2145
- if (dragging && dragging !== column.id) onMoveTo(dragging, column.id);
2146
- setDragging(null);
2181
+ onDragStart: (event) => {
2182
+ if (event.target.closest(".mz-dt__columns-controls")) {
2183
+ event.preventDefault();
2184
+ return;
2185
+ }
2186
+ setDragging(column.id);
2187
+ event.dataTransfer.effectAllowed = "move";
2188
+ try {
2189
+ event.dataTransfer.setData("text/plain", column.id);
2190
+ } catch {
2191
+ }
2192
+ },
2193
+ onDragEnd: endDrag,
2194
+ onDragOver: (event) => {
2195
+ if (!canDrop(column.id)) {
2196
+ event.dataTransfer.dropEffect = "none";
2197
+ return;
2198
+ }
2199
+ event.preventDefault();
2200
+ event.dataTransfer.dropEffect = "move";
2201
+ setDropTarget(column.id);
2202
+ },
2203
+ onDragLeave: () => setDropTarget((c) => c === column.id ? null : c),
2204
+ onDrop: (event) => {
2205
+ event.preventDefault();
2206
+ if (canDrop(column.id)) onMoveTo(dragging, column.id);
2207
+ endDrag();
2147
2208
  },
2148
2209
  children: [
2149
2210
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mz-dt__columns-grip", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(GripIcon, {}) }),
2150
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mz-dt__columns-label", children: label }),
2151
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mz-dt__columns-controls", children: [
2211
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mz-dt__columns-label", children: name }),
2212
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mz-dt__columns-controls", draggable: false, children: [
2152
2213
  /* @__PURE__ */ jsxRuntime.jsx(
2153
2214
  "button",
2154
2215
  {
2155
2216
  type: "button",
2156
2217
  className: "mz-dt__icon-btn mz-focusable",
2157
- disabled: index === 0,
2158
- onClick: () => onMove(column.id, -1),
2159
- "aria-label": labels.moveUp(label),
2218
+ disabled: !entry.previous,
2219
+ onClick: () => entry.previous && onMoveTo(column.id, entry.previous),
2220
+ "aria-label": labels.moveUp(name),
2160
2221
  children: "\u2191"
2161
2222
  }
2162
2223
  ),
@@ -2165,9 +2226,9 @@ function ColumnManager({
2165
2226
  {
2166
2227
  type: "button",
2167
2228
  className: "mz-dt__icon-btn mz-focusable",
2168
- disabled: index === ordered.length - 1,
2169
- onClick: () => onMove(column.id, 1),
2170
- "aria-label": labels.moveDown(label),
2229
+ disabled: !entry.next,
2230
+ onClick: () => entry.next && onMoveTo(column.id, entry.next),
2231
+ "aria-label": labels.moveDown(name),
2171
2232
  children: "\u2193"
2172
2233
  }
2173
2234
  ),
@@ -2175,14 +2236,12 @@ function ColumnManager({
2175
2236
  "button",
2176
2237
  {
2177
2238
  type: "button",
2178
- className: "mz-dt__icon-btn mz-focusable",
2239
+ className: "mz-dt__icon-btn mz-dt__pin mz-focusable",
2179
2240
  "data-active": pinned ? true : void 0,
2241
+ "data-pinned": pinned,
2180
2242
  onClick: () => onSetPinned(column.id, pinned === "left" ? "right" : pinned === "right" ? void 0 : "left"),
2181
- "aria-label": labels.pinning(
2182
- label,
2183
- pinned === "left" ? labels.pinnedLeft : pinned === "right" ? labels.pinnedRight : labels.notPinned
2184
- ),
2185
- title: pinned === "left" ? labels.pinnedLeft : pinned === "right" ? labels.pinnedRight : labels.notPinned,
2243
+ "aria-label": labels.pinning(name, pinTitle),
2244
+ title: pinTitle,
2186
2245
  children: /* @__PURE__ */ jsxRuntime.jsx(PinIcon, {})
2187
2246
  }
2188
2247
  ),
@@ -2193,7 +2252,7 @@ function ColumnManager({
2193
2252
  className: "mz-dt__icon-btn mz-focusable",
2194
2253
  disabled: column.hideable === false,
2195
2254
  onClick: () => onToggleHidden(column.id),
2196
- "aria-label": hidden ? labels.show(label) : labels.hide(label),
2255
+ "aria-label": hidden ? labels.show(name) : labels.hide(name),
2197
2256
  children: hidden ? /* @__PURE__ */ jsxRuntime.jsx(EyeOffIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(EyeIcon, {})
2198
2257
  }
2199
2258
  )
@@ -2646,6 +2705,7 @@ function DataTable({
2646
2705
  onLayoutChange,
2647
2706
  persistKey = null,
2648
2707
  toolbar,
2708
+ columnManager = true,
2649
2709
  autoFit = true,
2650
2710
  density = "normal",
2651
2711
  stickyHeader = true,
@@ -2674,7 +2734,6 @@ function DataTable({
2674
2734
  setWidth,
2675
2735
  toggleHidden,
2676
2736
  setPinned,
2677
- move,
2678
2737
  moveTo,
2679
2738
  reset,
2680
2739
  fitTo
@@ -2906,22 +2965,25 @@ function DataTable({
2906
2965
  className: cn("mz-dt", className),
2907
2966
  style: widthVars,
2908
2967
  children: [
2909
- (toolbar || chips.length > 0 || columns.some((c) => c.hideable !== false)) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mz-dt__toolbar", children: [
2910
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mz-dt__toolbar-main", children: toolbar }),
2911
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mz-dt__toolbar-side", children: /* @__PURE__ */ jsxRuntime.jsx(
2912
- ColumnManager,
2913
- {
2914
- columns,
2915
- layout,
2916
- labels: labelsProp,
2917
- onToggleHidden: toggleHidden,
2918
- onSetPinned: setPinned,
2919
- onMove: move,
2920
- onMoveTo: moveTo,
2921
- onReset: reset
2922
- }
2923
- ) })
2924
- ] }),
2968
+ (() => {
2969
+ const showManager = columnManager && columns.some((c) => c.hideable !== false);
2970
+ if (!toolbar && chips.length === 0 && !showManager) return null;
2971
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mz-dt__toolbar", children: [
2972
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mz-dt__toolbar-main", children: toolbar }),
2973
+ showManager && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mz-dt__toolbar-side", children: /* @__PURE__ */ jsxRuntime.jsx(
2974
+ ColumnManager,
2975
+ {
2976
+ columns,
2977
+ layout,
2978
+ labels: labelsProp,
2979
+ onToggleHidden: toggleHidden,
2980
+ onSetPinned: setPinned,
2981
+ onMoveTo: moveTo,
2982
+ onReset: reset
2983
+ }
2984
+ ) })
2985
+ ] });
2986
+ })(),
2925
2987
  chips.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mz-dt__chips", children: [
2926
2988
  chips.map(([id, value]) => /* @__PURE__ */ jsxRuntime.jsx(
2927
2989
  FilterChip,
@@ -3268,6 +3330,7 @@ exports.AlertDescription = AlertDescription;
3268
3330
  exports.AlertTitle = AlertTitle;
3269
3331
  exports.Avatar = Avatar;
3270
3332
  exports.AvatarFallback = AvatarFallback;
3333
+ exports.AvatarGroup = AvatarGroup;
3271
3334
  exports.AvatarImage = AvatarImage;
3272
3335
  exports.Badge = Badge;
3273
3336
  exports.Button = Button;