wenay-react2 1.0.35 → 1.0.37

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 (95) hide show
  1. package/README.md +8 -53
  2. package/lib/common/api.d.ts +28 -28
  3. package/lib/common/api.js +31 -31
  4. package/lib/common/src/components/Buttons/MiniButton.d.ts +1 -3
  5. package/lib/common/src/components/Buttons/MiniButton.js +1 -3
  6. package/lib/common/src/components/Dnd/{RNDFunc.d.ts → DragArea.d.ts} +1 -1
  7. package/lib/common/src/components/Dnd/{RNDFunc.js → DragArea.js} +1 -1
  8. package/lib/common/src/components/Dnd/{RNDFunc3.d.ts → FloatingWindow.d.ts} +7 -7
  9. package/lib/common/src/components/Dnd/{RNDFunc3.js → FloatingWindow.js} +10 -10
  10. package/lib/common/src/components/Dnd/OutlineDragDemo.d.ts +1 -0
  11. package/lib/common/src/components/Dnd/{DraggableOutlineDiv.js → OutlineDragDemo.js} +1 -2
  12. package/lib/common/src/components/Dnd/Resizable.js +1 -1
  13. package/lib/common/src/components/Dnd/index.d.ts +3 -3
  14. package/lib/common/src/components/Dnd/index.js +3 -3
  15. package/lib/common/src/components/Input.d.ts +5 -5
  16. package/lib/common/src/components/Input.js +10 -10
  17. package/lib/common/src/components/Menu/RightMenu.d.ts +25 -5
  18. package/lib/common/src/components/Menu/RightMenu.js +27 -19
  19. package/lib/common/src/components/Menu/RightMenuStore.d.ts +2 -2
  20. package/lib/common/src/components/Menu/RightMenuStore.js +1 -1
  21. package/lib/common/src/components/Modal/LeftModal.js +4 -4
  22. package/lib/common/src/components/Modal/Modal.d.ts +11 -17
  23. package/lib/common/src/components/Modal/Modal.js +15 -21
  24. package/lib/common/src/components/Modal/ModalContextProvider.d.ts +0 -6
  25. package/lib/common/src/components/Modal/ModalContextProvider.js +2 -9
  26. package/lib/common/src/components/Other.d.ts +2 -2
  27. package/lib/common/src/components/Other.js +5 -5
  28. package/lib/common/src/components/Parameters.d.ts +3 -3
  29. package/lib/common/src/components/Parameters.js +3 -3
  30. package/lib/common/src/components/{ParametersEngine.d.ts → ParamsEditor.d.ts} +1 -1
  31. package/lib/common/src/components/{ParametersEngine.js → ParamsEditor.js} +10 -10
  32. package/lib/common/src/components/Settings/SettingsDialog.d.ts +4 -4
  33. package/lib/common/src/components/Toolbar/Toolbar.d.ts +50 -37
  34. package/lib/common/src/components/Toolbar/Toolbar.js +60 -23
  35. package/lib/common/src/components/UiSlot/UiSlot.d.ts +3 -3
  36. package/lib/common/src/components/UiSlot/UiSlot.js +6 -6
  37. package/lib/common/src/grid/agGrid4/agGrid4.d.ts +4 -4
  38. package/lib/common/src/grid/agGrid4/agGrid4.js +6 -6
  39. package/lib/common/src/grid/agGrid4/index.d.ts +3 -3
  40. package/lib/common/src/grid/agGrid4/index.js +1 -1
  41. package/lib/common/src/grid/agGrid4/theme.d.ts +3 -3
  42. package/lib/common/src/grid/columnState/CardList.d.ts +11 -0
  43. package/lib/common/src/grid/columnState/CardList.js +28 -0
  44. package/lib/common/src/grid/columnState/ColumnDots.d.ts +9 -0
  45. package/lib/common/src/grid/columnState/ColumnDots.js +121 -0
  46. package/lib/common/src/grid/columnState/ColumnsMenu.d.ts +65 -0
  47. package/lib/common/src/grid/columnState/ColumnsMenu.js +123 -0
  48. package/lib/common/src/grid/columnState/columnState.d.ts +113 -0
  49. package/lib/common/src/grid/columnState/columnState.js +284 -0
  50. package/lib/common/src/grid/columnState/index.d.ts +4 -0
  51. package/lib/common/src/grid/columnState/index.js +4 -0
  52. package/lib/common/src/hooks/index.d.ts +1 -1
  53. package/lib/common/src/hooks/index.js +1 -1
  54. package/lib/common/src/hooks/useKeyboard.d.ts +18 -0
  55. package/lib/common/src/hooks/{useAddDownAnyKey.js → useKeyboard.js} +16 -24
  56. package/lib/common/src/hooks/useObserveStore.d.ts +12 -12
  57. package/lib/common/src/hooks/useObserveStore.js +2 -2
  58. package/lib/common/src/hooks/useOutside.d.ts +12 -19
  59. package/lib/common/src/hooks/useOutside.js +9 -16
  60. package/lib/common/src/hooks/useReorder.d.ts +4 -4
  61. package/lib/common/src/hooks/useReorderBoard.d.ts +15 -15
  62. package/lib/common/src/hooks/useReplay.d.ts +9 -9
  63. package/lib/common/src/hooks/useReplay.js +7 -7
  64. package/lib/common/src/logs/logs.d.ts +3 -3
  65. package/lib/common/src/logs/logs.js +11 -13
  66. package/lib/common/src/logs/{logs3.d.ts → logsContext.d.ts} +4 -4
  67. package/lib/common/src/logs/{logs3.js → logsContext.js} +4 -4
  68. package/lib/common/src/menu/menu.d.ts +16 -16
  69. package/lib/common/src/menu/menu.js +12 -11
  70. package/lib/common/src/menu/menuMouse.d.ts +71 -13
  71. package/lib/common/src/menu/menuMouse.js +189 -21
  72. package/lib/common/src/menu/menuR.d.ts +3 -3
  73. package/lib/common/src/menu/menuR.js +5 -5
  74. package/lib/common/src/styles/styleGrid.d.ts +1 -1
  75. package/lib/common/src/styles/tokens.d.ts +1 -1
  76. package/lib/common/src/styles/tokens.js +1 -1
  77. package/lib/common/src/utils/cache.d.ts +11 -11
  78. package/lib/common/src/utils/cache.js +0 -0
  79. package/lib/common/src/utils/gridRows.d.ts +37 -0
  80. package/lib/common/src/utils/{applyTransactionAsyncUpdate.js → gridRows.js} +6 -38
  81. package/lib/common/src/utils/index.d.ts +2 -2
  82. package/lib/common/src/utils/index.js +2 -2
  83. package/lib/common/src/utils/inputAutoStep.d.ts +2 -2
  84. package/lib/common/src/utils/inputAutoStep.js +26 -37
  85. package/lib/common/src/utils/{mapMemory.d.ts → memoryStore.d.ts} +13 -13
  86. package/lib/common/src/utils/{mapMemory.js → memoryStore.js} +32 -32
  87. package/lib/common/src/utils/observableMap.d.ts +5 -5
  88. package/lib/common/src/utils/observableMap.js +3 -3
  89. package/lib/common/updateBy.js +2 -2
  90. package/lib/style/style.css +3 -3
  91. package/lib/style/tokens.css +1 -1
  92. package/package.json +49 -49
  93. package/lib/common/src/components/Dnd/DraggableOutlineDiv.d.ts +0 -2
  94. package/lib/common/src/hooks/useAddDownAnyKey.d.ts +0 -24
  95. package/lib/common/src/utils/applyTransactionAsyncUpdate.d.ts +0 -53
@@ -1,21 +1,22 @@
1
1
  import React from 'react';
2
2
  /** createToolbar - a customizable, self-describing toolbar primitive.
3
3
  * Three decoupled layers: config (plain serializable data, persisted via
4
- * staticProps -> Cash, same mechanics as createUiSlot), Bar (renders visible
4
+ * memoryProps -> memoryCache, same mechanics as createUiSlot), Bar (renders visible
5
5
  * items in config order at config density) and Settings (a pure editor that
6
6
  * only reads/writes config) - so the SAME Settings element works both in the
7
7
  * Bar's own gear popover and in a global settings section.
8
8
  * v1 non-goals: no overflow/"more" menu (an overflow hook would live in Bar,
9
9
  * right after the visible-items map), no grouping, no cross-bar drag. */
10
- export type tToolbarItem = {
10
+ export type ToolbarItem = {
11
11
  /** stable id (persist key) */
12
12
  key: string;
13
13
  /** full human name - shown in the Settings list */
14
14
  title: string;
15
15
  /** short caption for 'label' density (falls back to title) */
16
16
  short?: string;
17
- /** compact glyph/icon for 'icon' density */
18
- icon: React.ReactNode;
17
+ /** compact glyph/icon for 'icon' density; absent = the first letters of
18
+ * short/title render as a text pseudo-icon */
19
+ icon?: React.ReactNode;
19
20
  /** full custom render; default = icon [+ short] by the density registry */
20
21
  render?: (density: string) => React.ReactNode;
21
22
  /** convenience for plain action buttons; interactive items can also handle clicks inside render() */
@@ -25,7 +26,7 @@ export type tToolbarItem = {
25
26
  /** cannot be hidden or reordered (pinned to its index in opts.items) */
26
27
  fixed?: boolean;
27
28
  };
28
- export type tToolbarConfig = {
29
+ export type ToolbarConfig = {
29
30
  /** item keys, display order */
30
31
  order: string[];
31
32
  visible: {
@@ -34,25 +35,51 @@ export type tToolbarConfig = {
34
35
  /** a key from the density registry ('icon' | 'label' | registered extras) */
35
36
  density: string;
36
37
  };
37
- export type tToolbarDensity = {
38
+ /** The order/visibility slice of a config - what an external source owns. */
39
+ export type UiListConfig = {
40
+ order: string[];
41
+ visible: {
42
+ [key: string]: boolean;
43
+ };
44
+ };
45
+ /** An external owner of order/visibility that a Toolbar can run on instead of
46
+ * its own store - e.g. columnState's listSource: the SAME config the grid
47
+ * syncs with, so dragging a column in the grid reorders the toolbar and
48
+ * vice versa. Density and the gear flag stay toolbar-local (persisted under
49
+ * the toolbar's own key). useConfig must be a React hook (subscription). */
50
+ export type UiListSource = {
51
+ useConfig: () => UiListConfig;
52
+ getConfig: () => UiListConfig;
53
+ setConfig: (next: UiListConfig) => void;
54
+ /** re-emitted as the toolbar's own onChange (grid-driven changes included) */
55
+ onChange?: (cb: (cfg: UiListConfig) => void) => () => void;
56
+ };
57
+ export type ToolbarDensity = {
38
58
  key: string;
39
59
  /** human name for the Settings segmented control */
40
60
  name: string;
41
61
  /** how one item renders at this density; absent = icon + (short ?? title) */
42
- renderItem?: (item: tToolbarItem) => React.ReactNode;
62
+ renderItem?: (item: ToolbarItem) => React.ReactNode;
43
63
  };
64
+ /** Icon with a text fallback: no glyph = the first letters of short/title
65
+ * (an "PR"-style pseudo-icon), so icon densities work for icon-less items. */
66
+ export declare function toolbarItemIcon(item: {
67
+ icon?: React.ReactNode;
68
+ short?: string;
69
+ title: string;
70
+ }): React.ReactNode;
44
71
  /** Register an extra density level. Re-register with the same key replaces the
45
72
  * previous one. The returned function removes exactly this registration. */
46
- export declare function registerToolbarDensity(d: tToolbarDensity): () => void;
73
+ export declare function registerToolbarDensity(d: ToolbarDensity): () => void;
47
74
  /** Current density registry (built-ins + registered). */
48
- export declare function getToolbarDensities(): readonly tToolbarDensity[];
75
+ export declare function getToolbarDensities(): readonly ToolbarDensity[];
49
76
  export declare function createToolbar(opts: {
50
- /** persistence key (staticProps -> Cash), like createUiSlot */
77
+ /** persistence key (memoryProps -> memoryCache), like createUiSlot */
51
78
  key: string;
52
79
  /** item descriptors; the config only ever references them by key */
53
- items: tToolbarItem[];
80
+ items: ToolbarItem[];
54
81
  /** defaults; missing fields are derived from items */
55
- def?: Partial<tToolbarConfig>;
82
+ def?: Partial<ToolbarConfig>;
56
83
  /** the gear button's face: icon/title default to a plain gear svg. The gear
57
84
  * renders only when Bar mounts with settings, AND visible['__settings'] is
58
85
  * not false - the Settings editor shows a separated toggle row for it. */
@@ -60,6 +87,12 @@ export declare function createToolbar(opts: {
60
87
  title?: string;
61
88
  icon?: React.ReactNode;
62
89
  };
90
+ /** external owner of order/visibility (columnState.api.listSource etc.):
91
+ * the toolbar becomes a VIEW over that config - Bar/Settings edit it, and
92
+ * outside changes (a column dragged in the grid) reorder the toolbar.
93
+ * Item keys should match the source's keys 1:1. Density and the gear flag
94
+ * remain in the toolbar's own store under `key`. Default: own store. */
95
+ source?: UiListSource;
63
96
  }): {
64
97
  Bar: (p?: {
65
98
  className?: string;
@@ -71,35 +104,15 @@ export declare function createToolbar(opts: {
71
104
  activeClassName?: string;
72
105
  }) => import("react/jsx-runtime").JSX.Element;
73
106
  api: {
74
- useConfig: () => tToolbarConfig;
107
+ useConfig: () => ToolbarConfig;
75
108
  useItems: () => {
76
- item: tToolbarItem;
109
+ item: ToolbarItem;
77
110
  density: string;
78
111
  content: string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null | undefined;
79
112
  }[];
80
- getConfig: () => tToolbarConfig;
81
- setConfig: (next: tToolbarConfig) => void;
113
+ getConfig: () => ToolbarConfig;
114
+ setConfig: (next: ToolbarConfig) => void;
82
115
  reset: () => void;
83
- onChange: {
84
- func: import("wenay-common2").Listener<[tToolbarConfig]>;
85
- isRun: () => boolean;
86
- run: () => void;
87
- close: () => void;
88
- eventClose: (cb: () => void) => () => void;
89
- onClose: (cb: () => void) => () => void;
90
- removeEventClose: (cb: () => void) => void;
91
- on: import("wenay-common2").ListenOn<[tToolbarConfig]>;
92
- off: (k: import("wenay-common2").Listener<[tToolbarConfig]> | (string | symbol) | null) => void;
93
- addListen: (cb: import("wenay-common2").Listener<[tToolbarConfig]>, opts?: {
94
- cbClose?: () => void;
95
- key?: string | symbol;
96
- }) => () => void;
97
- removeListen: (k: import("wenay-common2").Listener<[tToolbarConfig]> | (string | symbol) | null) => void;
98
- once: (cb: import("wenay-common2").Listener<[tToolbarConfig]>, opts?: {
99
- key?: string | symbol;
100
- }) => () => void;
101
- count: () => number;
102
- readonly getAllKeys: (string | symbol)[];
103
- };
116
+ onChange: import("wenay-common2").ListenApi<[ToolbarConfig]>;
104
117
  };
105
118
  };
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
- import { UseListen } from 'wenay-common2';
3
+ import { listen as createListen } from 'wenay-common2';
4
4
  import { renderBy, updateBy } from '../../../updateBy';
5
- import { staticGetAdd, staticMarkDirty } from '../../utils/mapMemory';
6
- import { DivOutsideClick } from '../../hooks/useOutside';
5
+ import { memoryGetOrCreate, memoryMarkDirty } from '../../utils/memoryStore';
6
+ import { OutsideClickArea } from '../../hooks/useOutside';
7
7
  import { useReorder } from '../../hooks/useReorder';
8
8
  // Module singleton (closure + updateBy subscription, no React context) - same
9
9
  // pattern as the settings-section registry. Two built-in levels; a third
@@ -12,8 +12,13 @@ const densities = { list: [
12
12
  { key: 'icon', name: 'Icons', renderItem: itemIconOnly },
13
13
  { key: 'label', name: 'Icons + labels' },
14
14
  ] };
15
+ /** Icon with a text fallback: no glyph = the first letters of short/title
16
+ * (an "PR"-style pseudo-icon), so icon densities work for icon-less items. */
17
+ export function toolbarItemIcon(item) {
18
+ return item.icon ?? _jsx("span", { style: { fontSize: 10, fontWeight: 700, letterSpacing: 0.5, textTransform: 'uppercase' }, children: (item.short ?? item.title).slice(0, 3) });
19
+ }
15
20
  function itemIconOnly(item) {
16
- return item.icon;
21
+ return toolbarItemIcon(item);
17
22
  }
18
23
  /** Register an extra density level. Re-register with the same key replaces the
19
24
  * previous one. The returned function removes exactly this registration. */
@@ -42,7 +47,7 @@ function itemContent(item, densityKey) {
42
47
  const d = densities.list.find(e => e.key == densityKey);
43
48
  if (d?.renderItem)
44
49
  return d.renderItem(item);
45
- return _jsxs(_Fragment, { children: [_jsx("span", { className: 'wenayTbIcon', children: item.icon }), _jsx("span", { className: 'wenayTbLabel', children: item.short ?? item.title })] });
50
+ return _jsxs(_Fragment, { children: [item.icon != null && _jsx("span", { className: 'wenayTbIcon', children: item.icon }), _jsx("span", { className: 'wenayTbLabel', children: item.short ?? item.title })] });
46
51
  }
47
52
  /** Reserved visible-map key for the bar's settings (gear) button: not part of
48
53
  * order (the gear always sits at the bar edge), but toggleable like an item. */
@@ -53,15 +58,24 @@ export function createToolbar(opts) {
53
58
  visible: opts.def?.visible ? { ...opts.def.visible } : Object.fromEntries(opts.items.map(i => [i.key, i.defaultVisible != false])),
54
59
  density: opts.def?.density ?? densities.list[0].key,
55
60
  });
56
- const st = staticGetAdd(opts.key, defConfig());
57
- const [emitChange, onChange] = UseListen();
61
+ const st = memoryGetOrCreate(opts.key, defConfig());
62
+ const [emitChange, onChange] = createListen();
63
+ // ext is fixed for the controller's lifetime, so hook call order inside
64
+ // useConfig/Bar/Settings never changes for a given toolbar instance
65
+ const ext = opts.source;
66
+ // outside edits of the external config (grid drags...) must reach the
67
+ // toolbar's own subscribers too; module-lifetime subscription by design
68
+ ext?.onChange?.(() => emitChange(normalize()));
69
+ /** raw order/visible as stored - own store or the external source */
70
+ const rawList = () => ext ? ext.getConfig() : { order: st.order, visible: st.visible };
58
71
  /** The persisted state may be stale or partial (older app version, removed
59
72
  * items, an unregistered density) - never crash, never drop user data that
60
73
  * still applies: unknown keys are filtered out, missing items are appended
61
74
  * (default-visible), fixed items are pinned back to their descriptor index. */
62
75
  function normalize() {
76
+ const raw = rawList();
63
77
  const known = new Set(opts.items.map(i => i.key));
64
- const rawOrder = Array.isArray(st.order) ? st.order : [];
78
+ const rawOrder = Array.isArray(raw.order) ? raw.order : [];
65
79
  const order = rawOrder.filter(k => known.has(k) && !opts.items.find(i => i.key == k)?.fixed);
66
80
  for (const it of opts.items)
67
81
  if (!it.fixed && order.indexOf(it.key) == -1)
@@ -70,29 +84,52 @@ export function createToolbar(opts) {
70
84
  if (it.fixed)
71
85
  order.splice(Math.min(i, order.length), 0, it.key);
72
86
  });
73
- const rawVisible = st.visible && typeof st.visible == 'object' ? st.visible : {};
87
+ const rawVisible = raw.visible && typeof raw.visible == 'object' ? raw.visible : {};
74
88
  const visible = {};
75
89
  for (const it of opts.items)
76
90
  visible[it.key] = it.fixed ? true : (rawVisible[it.key] ?? it.defaultVisible != false);
77
- visible[SETTINGS_KEY] = typeof rawVisible[SETTINGS_KEY] == 'boolean' ? rawVisible[SETTINGS_KEY] : true;
91
+ // the gear flag is toolbar-local: an external source only owns items
92
+ const gearRaw = (ext ? st.visible : rawVisible) ?? {};
93
+ visible[SETTINGS_KEY] = typeof gearRaw[SETTINGS_KEY] == 'boolean' ? gearRaw[SETTINGS_KEY] : true;
78
94
  const density = typeof st.density == 'string' && densities.list.some(d => d.key == st.density)
79
95
  ? st.density : (opts.def?.density ?? densities.list[0].key);
80
96
  return { order, visible, density };
81
97
  }
82
98
  /** Every edit funnels through here: mutate the persisted object in place
83
99
  * (identity is the updateBy/renderBy subscription key), announce, mark the
84
- * cache dirty, emit outward. */
100
+ * cache dirty, emit outward. With an external source the items' order and
101
+ * visibility go THERE (its own change flow re-emits); density + gear flag
102
+ * always stay in the toolbar's own store. */
85
103
  function setConfig(next) {
86
- st.order = next.order.slice();
87
- st.visible = { ...next.visible };
88
- st.density = next.density;
89
- renderBy(st);
90
- staticMarkDirty(opts.key);
91
- emitChange(normalize());
104
+ if (ext) {
105
+ const visible = { ...next.visible };
106
+ delete visible[SETTINGS_KEY];
107
+ st.visible = { ...st.visible, [SETTINGS_KEY]: next.visible[SETTINGS_KEY] != false };
108
+ st.density = next.density;
109
+ renderBy(st);
110
+ memoryMarkDirty(opts.key);
111
+ ext.setConfig({ order: next.order.slice(), visible });
112
+ // the source's own onChange already re-emitted; emit only when it can't
113
+ if (!ext.onChange)
114
+ emitChange(normalize());
115
+ }
116
+ else {
117
+ st.order = next.order.slice();
118
+ st.visible = { ...next.visible };
119
+ st.density = next.density;
120
+ renderBy(st);
121
+ memoryMarkDirty(opts.key);
122
+ emitChange(normalize());
123
+ }
92
124
  }
93
125
  const getConfig = () => normalize();
94
- function useConfig() {
126
+ /** subscription to everything the toolbar renders from (hook) */
127
+ function useSubscribe() {
95
128
  updateBy(st);
129
+ ext?.useConfig(); // ext is per-instance constant - hook order is stable
130
+ }
131
+ function useConfig() {
132
+ useSubscribe();
96
133
  return normalize();
97
134
  }
98
135
  /** Headless bar: the ordered, visibility-filtered items plus their rendered
@@ -102,7 +139,7 @@ export function createToolbar(opts) {
102
139
  * consumer re-renders from this list rather than the library re-parenting
103
140
  * someone else's nodes.) */
104
141
  function useItems() {
105
- updateBy(st);
142
+ useSubscribe();
106
143
  updateBy(densities);
107
144
  const cfg = normalize();
108
145
  const byKey = new Map(opts.items.map(i => [i.key, i]));
@@ -132,7 +169,7 @@ export function createToolbar(opts) {
132
169
  * global settings menu. popAlign: which bar edge the popover sticks to -
133
170
  * 'right' (default, for bars in a top-right corner) or 'left'. */
134
171
  function Bar(p = {}) {
135
- updateBy(st);
172
+ useSubscribe();
136
173
  updateBy(densities);
137
174
  const cfg = normalize();
138
175
  const [open, setOpen] = useState(false);
@@ -142,7 +179,7 @@ export function createToolbar(opts) {
142
179
  if (!it || cfg.visible[k] == false)
143
180
  return null;
144
181
  return _jsx("div", { className: 'wenayTbItem', title: cfg.density == 'icon' ? it.title : undefined, onClick: it.onClick, children: itemContent(it, cfg.density) }, k);
145
- }), p.settings && cfg.visible[SETTINGS_KEY] != false && _jsxs(DivOutsideClick, { className: 'wenayTbGear', status: open, outsideClick: () => setOpen(false), children: [_jsx("div", { className: 'wenayTbItem', title: settingsTitle(), onClick: () => setOpen(v => !v), children: settingsIcon() }), open && _jsx("div", { className: p.popAlign == 'left' ? 'wenayTbPop wenayTbPopLeft' : 'wenayTbPop', children: _jsx(Settings, {}) })] })] });
182
+ }), p.settings && cfg.visible[SETTINGS_KEY] != false && _jsxs(OutsideClickArea, { className: 'wenayTbGear', status: open, outsideClick: () => setOpen(false), children: [_jsx("div", { className: 'wenayTbItem', title: settingsTitle(), onClick: () => setOpen(v => !v), children: settingsIcon() }), open && _jsx("div", { className: p.popAlign == 'left' ? 'wenayTbPop wenayTbPopLeft' : 'wenayTbPop', children: _jsx(Settings, {}) })] })] });
146
183
  }
147
184
  /** The pure editor over config: density segments + one row per item
148
185
  * (visibility checkbox, icon preview, title, drag handle). Reorder rides the
@@ -152,7 +189,7 @@ export function createToolbar(opts) {
152
189
  * never move in the preview and a drop never lands elsewhere than shown.
153
190
  * Plus arrow keys on the focused handle; fixed rows have neither. */
154
191
  function Settings(p = {}) {
155
- updateBy(st);
192
+ useSubscribe();
156
193
  updateBy(densities);
157
194
  const cfg = normalize();
158
195
  const base = p.className ?? 'wenaySegBtn';
@@ -199,7 +236,7 @@ export function createToolbar(opts) {
199
236
  if (!e.target.closest('input'))
200
237
  e.currentTarget.querySelector('.wenayTbHandle')?.focus();
201
238
  r.props.onMouseDown(e);
202
- }, onTouchStart: it.fixed ? undefined : r.props.onTouchStart, children: [_jsx("input", { type: 'checkbox', disabled: it.fixed, checked: cfg.visible[k] != false, onChange: () => setConfig({ ...cfg, visible: { ...cfg.visible, [k]: !(cfg.visible[k] != false) } }) }), _jsx("span", { className: 'wenayTbIcon', children: it.icon }), _jsx("span", { className: 'wenayTbRowTitle', children: it.title }), !it.fixed && _jsx("div", { className: 'wenayTbHandle', tabIndex: 0, title: 'Drag or arrow keys to reorder', onKeyDown: e => onHandleKey(k, e), children: "\u283F" })] }, k);
239
+ }, onTouchStart: it.fixed ? undefined : r.props.onTouchStart, children: [_jsx("input", { type: 'checkbox', disabled: it.fixed, checked: cfg.visible[k] != false, onChange: () => setConfig({ ...cfg, visible: { ...cfg.visible, [k]: !(cfg.visible[k] != false) } }) }), _jsx("span", { className: 'wenayTbIcon', children: toolbarItemIcon(it) }), _jsx("span", { className: 'wenayTbRowTitle', children: it.title }), !it.fixed && _jsx("div", { className: 'wenayTbHandle', tabIndex: 0, title: 'Drag or arrow keys to reorder', onKeyDown: e => onHandleKey(k, e), children: "\u283F" })] }, k);
203
240
  }) }), _jsxs("div", { className: 'wenayTbRow wenayTbRowMeta', children: [_jsx("input", { type: 'checkbox', checked: cfg.visible[SETTINGS_KEY] != false, onChange: () => setConfig({ ...cfg, visible: { ...cfg.visible, [SETTINGS_KEY]: !(cfg.visible[SETTINGS_KEY] != false) } }) }), _jsx("span", { className: 'wenayTbIcon', children: settingsIcon() }), _jsx("span", { className: 'wenayTbRowTitle', children: settingsTitle() })] })] });
204
241
  }
205
242
  return {
@@ -1,8 +1,8 @@
1
1
  import React from "react";
2
2
  /** One UI block shown in exactly one of several mount points; the point is a persisted setting.
3
- * Persistence rides the existing staticProps -> Cash mechanics: staticProps is observable,
4
- * setPlace announces its in-place mutation (staticMarkDirty), the app decides when to save
5
- * via Cash.onDirty - same as window state (ExRNDMap3 etc.).
3
+ * Persistence rides the existing memoryProps -> memoryCache mechanics: memoryProps is observable,
4
+ * setPlace announces its in-place mutation (memoryMarkDirty), the app decides when to save
5
+ * via memoryCache.onDirty - same as window state (floatingWindowMap etc.).
6
6
  * Mount points render <Slot place="..."> themselves and decide nothing: the slot compares
7
7
  * the persisted place with its own and renders children only on a match. */
8
8
  export declare function createUiSlot<Places extends string>(opts: {
@@ -1,14 +1,14 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { renderBy, updateBy } from "../../../updateBy";
3
- import { staticGetAdd, staticMarkDirty } from "../../utils/mapMemory";
3
+ import { memoryGetOrCreate, memoryMarkDirty } from "../../utils/memoryStore";
4
4
  /** One UI block shown in exactly one of several mount points; the point is a persisted setting.
5
- * Persistence rides the existing staticProps -> Cash mechanics: staticProps is observable,
6
- * setPlace announces its in-place mutation (staticMarkDirty), the app decides when to save
7
- * via Cash.onDirty - same as window state (ExRNDMap3 etc.).
5
+ * Persistence rides the existing memoryProps -> memoryCache mechanics: memoryProps is observable,
6
+ * setPlace announces its in-place mutation (memoryMarkDirty), the app decides when to save
7
+ * via memoryCache.onDirty - same as window state (floatingWindowMap etc.).
8
8
  * Mount points render <Slot place="..."> themselves and decide nothing: the slot compares
9
9
  * the persisted place with its own and renders children only on a match. */
10
10
  export function createUiSlot(opts) {
11
- const st = staticGetAdd(opts.key, { place: opts.def });
11
+ const st = memoryGetOrCreate(opts.key, { place: opts.def });
12
12
  // a stored place may no longer exist after an app update - fall back to def
13
13
  const isPlace = (p) => typeof p == "string" && p in opts.places;
14
14
  const getPlace = () => isPlace(st.place) ? st.place : opts.def;
@@ -17,7 +17,7 @@ export function createUiSlot(opts) {
17
17
  return;
18
18
  st.place = p;
19
19
  renderBy(st);
20
- staticMarkDirty(opts.key);
20
+ memoryMarkDirty(opts.key);
21
21
  };
22
22
  function Slot(p) {
23
23
  updateBy(st);
@@ -20,7 +20,7 @@ export type UseAgGridOptions<T> = {
20
20
  *
21
21
  * const grid = useAgGrid<Row>({ getId })
22
22
  * const grid = useAgGrid({ core: mainTable })
23
- * <AgGridMy<Row> controller={grid} columnDefs={cols} />
23
+ * <AgGridTable<Row> controller={grid} columnDefs={cols} />
24
24
  * grid.update({ newData })
25
25
  */
26
26
  export declare function useAgGrid<T>(options?: UseAgGridOptions<T>): {
@@ -50,7 +50,7 @@ export declare function useAgGrid<T>(options?: UseAgGridOptions<T>): {
50
50
  flushAsyncTransactions: () => boolean;
51
51
  };
52
52
  export type AgGridController<T> = ReturnType<typeof useAgGrid<T>>;
53
- export type AgGridMyProps<T> = AgGridReactProps<T> & {
53
+ export type AgGridTableProps<T> = AgGridReactProps<T> & {
54
54
  /** Controller from useAgGrid: all wiring (getRowId, ready/destroy, sync) is inside. */
55
55
  controller?: AgGridController<T>;
56
56
  /** Declarative row upsert for simple cases without a controller. */
@@ -58,6 +58,6 @@ export type AgGridMyProps<T> = AgGridReactProps<T> & {
58
58
  /** Auto-fit columns to the container. Defaults to true. */
59
59
  autoSizeColumns?: boolean;
60
60
  };
61
- declare function AgGridMyInner<T>(props: AgGridMyProps<T>): import("react/jsx-runtime").JSX.Element;
62
- export declare const AgGridMy: typeof AgGridMyInner;
61
+ declare function AgGridTableInner<T>(props: AgGridTableProps<T>): import("react/jsx-runtime").JSX.Element;
62
+ export declare const AgGridTable: typeof AgGridTableInner;
63
63
  export {};
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- // Layer 2 (React): headless hook over the core + custom <AgGridMy> component.
3
- // The hook does NOT render; it returns a controller. AgGridMy is our AgGridReact with
2
+ // Layer 2 (React): headless hook over the core + custom <AgGridTable> component.
3
+ // The hook does NOT render; it returns a controller. AgGridTable is our AgGridReact with
4
4
  // project defaults (theme, memo, auto sizing, selection, lifecycle). Wiring is the
5
5
  // controller prop; bare <AgGridReact> can still spread gridProps (as in agGrid3).
6
6
  import { memo, useEffect, useMemo, useRef, useState } from 'react';
@@ -24,7 +24,7 @@ function ensureAgGridModules() {
24
24
  *
25
25
  * const grid = useAgGrid<Row>({ getId })
26
26
  * const grid = useAgGrid({ core: mainTable })
27
- * <AgGridMy<Row> controller={grid} columnDefs={cols} />
27
+ * <AgGridTable<Row> controller={grid} columnDefs={cols} />
28
28
  * grid.update({ newData })
29
29
  */
30
30
  export function useAgGrid(options) {
@@ -97,11 +97,11 @@ export function useAgGrid(options) {
97
97
  };
98
98
  }, [core, gridProps]);
99
99
  }
100
- // --- AgGridMy: our grid with project defaults --------------------------------
100
+ // --- AgGridTable: our grid with project defaults --------------------------------
101
101
  // v35: the canonical row-selection form is an object, not the legacy "multiple" string.
102
102
  // Stable module-level reference so the grid does not re-evaluate the option on each render.
103
103
  const ROW_SELECTION = { mode: 'multiRow' };
104
- function AgGridMyInner(props) {
104
+ function AgGridTableInner(props) {
105
105
  const { controller, data, autoSizeColumns = true, defaultColDef, theme, getRowId, onGridReady, onGridPreDestroyed, ...rest } = props;
106
106
  // Own controller is overlay-safe: rowData grids without a controller must not be cleared on attach.
107
107
  const own = useAgGrid({
@@ -152,4 +152,4 @@ function AgGridMyInner(props) {
152
152
  }
153
153
  // memo: the grid does not re-render from unrelated page state; data updates bypass
154
154
  // render (controller.updateData). The cast is required because memo() erases the component generic.
155
- export const AgGridMy = memo(AgGridMyInner);
155
+ export const AgGridTable = memo(AgGridTableInner);
@@ -2,9 +2,9 @@ export { createGridBuffer } from './core';
2
2
  export type { BufferTable, CleanArgs, CreateGridBufferOptions, GetId, GridApiLike, GridBufferCore, GridBufferMode, GridTransaction, PushOptions, RowId, UpdateArgs, } from './core';
3
3
  export { createColumnBuffer } from './columnBuffer';
4
4
  export type { ColumnApplyContext, ColumnAttach, ColumnBuffer } from './columnBuffer';
5
- export { useAgGrid, AgGridMy } from './agGrid4';
6
- export type { AgGridController, AgGridMyProps, UseAgGridOptions } from './agGrid4';
5
+ export { useAgGrid, AgGridTable } from './agGrid4';
6
+ export type { AgGridController, AgGridTableProps, UseAgGridOptions } from './agGrid4';
7
7
  export { numericComparator, colDefCentered, colDefWrap } from './gridUtils';
8
8
  export type { NumberPair } from './gridUtils';
9
9
  export { useAgGridTheme, buildAgTheme } from './theme';
10
- export type { tThemeMode } from './theme';
10
+ export type { ThemeMode } from './theme';
@@ -1,5 +1,5 @@
1
1
  export { createGridBuffer } from './core';
2
2
  export { createColumnBuffer } from './columnBuffer';
3
- export { useAgGrid, AgGridMy } from './agGrid4';
3
+ export { useAgGrid, AgGridTable } from './agGrid4';
4
4
  export { numericComparator, colDefCentered, colDefWrap } from './gridUtils';
5
5
  export { useAgGridTheme, buildAgTheme } from './theme';
@@ -1,7 +1,7 @@
1
- export type tThemeMode = 'light' | 'dark';
1
+ export type ThemeMode = 'light' | 'dark';
2
2
  /** Pure ag-grid theme builder from mode. No React. Cached per mode: one shared
3
3
  * theme object across all grids instead of one per component instance.
4
4
  * dark uses the same parts and params as legacy GridStyleDefault for a consistent grid look. */
5
- export declare function buildAgTheme(mode: tThemeMode): import("ag-grid-community").Theme<import("ag-grid-community").ThemeDefaultParams>;
5
+ export declare function buildAgTheme(mode: ThemeMode): import("ag-grid-community").Theme<import("ag-grid-community").ThemeDefaultParams>;
6
6
  /** Application theme; default is dark, as in production. */
7
- export declare function useAgGridTheme(mode?: tThemeMode): import("ag-grid-community").Theme<import("ag-grid-community").ThemeDefaultParams>;
7
+ export declare function useAgGridTheme(mode?: ThemeMode): import("ag-grid-community").Theme<import("ag-grid-community").ThemeDefaultParams>;
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import type { ColumnStateController } from './columnState';
3
+ export declare function CardList<T extends object>(p: {
4
+ state: ColumnStateController;
5
+ data: readonly T[];
6
+ getId?: (row: T, index: number) => string;
7
+ /** custom field renderer; default = String(row[key]) */
8
+ renderValue?: (key: string, row: T) => React.ReactNode;
9
+ className?: string;
10
+ style?: React.CSSProperties;
11
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ function cmpValues(a, b) {
3
+ if (typeof a == 'number' && typeof b == 'number')
4
+ return a - b;
5
+ if (a == null && b == null)
6
+ return 0;
7
+ if (a == null)
8
+ return -1;
9
+ if (b == null)
10
+ return 1;
11
+ return String(a).localeCompare(String(b));
12
+ }
13
+ export function CardList(p) {
14
+ const cfg = p.state.api.useConfig();
15
+ const cols = p.state.columns;
16
+ const byKey = new Map(cols.map(c => [c.key, c]));
17
+ const keys = p.state.api.visibleKeys();
18
+ const titleKey = cols.find(c => c.cardRole == 'title' && cfg.visible[c.key] != false)?.key ?? keys[0];
19
+ const accentKey = cols.find(c => c.cardRole == 'accent' && cfg.visible[c.key] != false)?.key;
20
+ const fieldKeys = keys.filter(k => k != titleKey && k != accentKey);
21
+ const value = (key, row) => p.renderValue?.(key, row) ?? String(row[key] ?? '');
22
+ const rows = [...p.data];
23
+ if (cfg.sort) { // sticky sort: applies even when its column is hidden
24
+ const { key, dir } = cfg.sort;
25
+ rows.sort((a, b) => cmpValues(a[key], b[key]) * (dir == 'asc' ? 1 : -1));
26
+ }
27
+ return _jsx("div", { className: p.className, style: { display: 'grid', gap: 8, ...p.style }, children: rows.map((row, i) => (_jsxs("div", { style: { border: '1px solid #d0d7de', borderRadius: 8, padding: '8px 10px', background: '#fff' }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: fieldKeys.length ? 6 : 0 }, children: [_jsx("b", { style: { fontSize: 14, flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, children: titleKey ? value(titleKey, row) : '' }), accentKey && _jsx("span", { style: { fontSize: 11, padding: '1px 8px', borderRadius: 10, background: '#ddf4ff', color: '#0969da', whiteSpace: 'nowrap' }, children: value(accentKey, row) })] }), fieldKeys.map(k => (_jsxs("div", { style: { display: 'flex', gap: 10, fontSize: 12, lineHeight: 1.7 }, children: [_jsx("span", { style: { color: '#57606a', minWidth: 72 }, children: byKey.get(k)?.title ?? k }), _jsx("span", { style: { flex: 1, textAlign: 'right', overflow: 'hidden', textOverflow: 'ellipsis' }, children: value(k, row) })] }, k)))] }, p.getId?.(row, i) ?? i))) });
28
+ }
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import type { ColumnStateController } from './columnState';
3
+ export declare function ColumnDots(p: {
4
+ state: ColumnStateController;
5
+ /** max simultaneous dots (default 4) */
6
+ max?: number;
7
+ className?: string;
8
+ style?: React.CSSProperties;
9
+ }): import("react/jsx-runtime").JSX.Element;