@mshuja288/aksuicore 0.4.2 → 0.4.3
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/CHANGELOG.md +7 -0
- package/dist/index.cjs +94 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +94 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/patterns/RecordWorkspace.tsx +116 -10
package/package.json
CHANGED
|
@@ -102,6 +102,48 @@ function defaultVisibleKeys<T>(columns: TableColumn<T>[]) {
|
|
|
102
102
|
return columns.filter((column) => column.defaultVisible !== false).map((column) => column.key);
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
/** Shared across all RecordWorkspace tables (preview + side rail). */
|
|
106
|
+
const WORKSPACE_CHROME_KEY = "aksui.workspace.chrome";
|
|
107
|
+
|
|
108
|
+
type WorkspaceChrome = {
|
|
109
|
+
previewEnabled: boolean;
|
|
110
|
+
sideOpen: boolean;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
function readWorkspaceChrome(): WorkspaceChrome {
|
|
114
|
+
if (typeof window === "undefined") {
|
|
115
|
+
return { previewEnabled: false, sideOpen: false };
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
const raw = window.localStorage.getItem(WORKSPACE_CHROME_KEY);
|
|
119
|
+
if (!raw) {
|
|
120
|
+
return { previewEnabled: false, sideOpen: false };
|
|
121
|
+
}
|
|
122
|
+
const parsed = JSON.parse(raw) as Partial<WorkspaceChrome>;
|
|
123
|
+
return {
|
|
124
|
+
previewEnabled: Boolean(parsed.previewEnabled),
|
|
125
|
+
sideOpen: Boolean(parsed.sideOpen),
|
|
126
|
+
};
|
|
127
|
+
} catch {
|
|
128
|
+
return { previewEnabled: false, sideOpen: false };
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function writeWorkspaceChrome(chrome: WorkspaceChrome) {
|
|
133
|
+
if (typeof window === "undefined") {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
window.localStorage.setItem(WORKSPACE_CHROME_KEY, JSON.stringify(chrome));
|
|
138
|
+
} catch {
|
|
139
|
+
/* ignore quota / private mode */
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function filtersPrefsKey(columnPrefsKey: string | undefined) {
|
|
144
|
+
return columnPrefsKey ? `${columnPrefsKey}.filters` : undefined;
|
|
145
|
+
}
|
|
146
|
+
|
|
105
147
|
function readStoredColumnKeys(prefsKey: string | undefined, fallback: string[], allowed: Set<string>) {
|
|
106
148
|
if (!prefsKey || typeof window === "undefined") {
|
|
107
149
|
return fallback;
|
|
@@ -133,6 +175,48 @@ function writeStoredColumnKeys(prefsKey: string | undefined, keys: string[]) {
|
|
|
133
175
|
}
|
|
134
176
|
}
|
|
135
177
|
|
|
178
|
+
function readStoredFilters(prefsKey: string | undefined, allowed: Set<string>): Record<string, string> {
|
|
179
|
+
if (!prefsKey || typeof window === "undefined") {
|
|
180
|
+
return {};
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
const raw = window.localStorage.getItem(prefsKey);
|
|
184
|
+
if (!raw) {
|
|
185
|
+
return {};
|
|
186
|
+
}
|
|
187
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
188
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
189
|
+
return {};
|
|
190
|
+
}
|
|
191
|
+
const next: Record<string, string> = {};
|
|
192
|
+
for (const [key, value] of Object.entries(parsed as Record<string, unknown>)) {
|
|
193
|
+
if (allowed.has(key) && typeof value === "string" && value.trim()) {
|
|
194
|
+
next[key] = value;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return next;
|
|
198
|
+
} catch {
|
|
199
|
+
return {};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function writeStoredFilters(prefsKey: string | undefined, filters: Record<string, string>) {
|
|
204
|
+
if (!prefsKey || typeof window === "undefined") {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
try {
|
|
208
|
+
const trimmed: Record<string, string> = {};
|
|
209
|
+
for (const [key, value] of Object.entries(filters)) {
|
|
210
|
+
if (value.trim()) {
|
|
211
|
+
trimmed[key] = value;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
window.localStorage.setItem(prefsKey, JSON.stringify(trimmed));
|
|
215
|
+
} catch {
|
|
216
|
+
/* ignore quota / private mode */
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
136
220
|
function compareColumnValues<T>(column: TableColumn<T>, left: T, right: T) {
|
|
137
221
|
const leftRaw = column.display ? column.display(left) : column.value(left);
|
|
138
222
|
const rightRaw = column.display ? column.display(right) : column.value(right);
|
|
@@ -330,7 +414,11 @@ export function RecordWorkspace<T>({
|
|
|
330
414
|
importBusy?: boolean;
|
|
331
415
|
/** Column checklist in the side rail. Default true. */
|
|
332
416
|
showColumnPicker?: boolean;
|
|
333
|
-
/**
|
|
417
|
+
/**
|
|
418
|
+
* Persist visible column keys in localStorage under this key.
|
|
419
|
+
* Also persists filter values at `${columnPrefsKey}.filters`.
|
|
420
|
+
* Preview + side-rail open/collapsed use a shared key across all tables (`aksui.workspace.chrome`).
|
|
421
|
+
*/
|
|
334
422
|
columnPrefsKey?: string;
|
|
335
423
|
/** Controlled visible column keys. */
|
|
336
424
|
visibleColumnKeys?: string[];
|
|
@@ -350,9 +438,12 @@ export function RecordWorkspace<T>({
|
|
|
350
438
|
const [internalVisibleKeys, setInternalVisibleKeys] = useState<string[]>(() =>
|
|
351
439
|
readStoredColumnKeys(columnPrefsKey, fallbackKeys, allowedKeys),
|
|
352
440
|
);
|
|
353
|
-
const
|
|
441
|
+
const filterStorageKey = filtersPrefsKey(columnPrefsKey);
|
|
442
|
+
const [filters, setFilters] = useState<Record<string, string>>(() =>
|
|
443
|
+
readStoredFilters(filterStorageKey, allowedKeys),
|
|
444
|
+
);
|
|
354
445
|
const [sort, setSort] = useState<SortState | null>(null);
|
|
355
|
-
const [sideOpen, setSideOpen] = useState(
|
|
446
|
+
const [sideOpen, setSideOpen] = useState(() => readWorkspaceChrome().sideOpen);
|
|
356
447
|
const [toolsDrawerOpen, setToolsDrawerOpen] = useState(false);
|
|
357
448
|
const [downloadOpen, setDownloadOpen] = useState(false);
|
|
358
449
|
const [bulkOpen, setBulkOpen] = useState(false);
|
|
@@ -361,7 +452,7 @@ export function RecordWorkspace<T>({
|
|
|
361
452
|
const [bulkReport, setBulkReport] = useState<BulkImportResult | null>(null);
|
|
362
453
|
const bulkFileInputRef = useRef<HTMLInputElement | null>(null);
|
|
363
454
|
const [columnsOpen, setColumnsOpen] = useState(false);
|
|
364
|
-
const [previewEnabled, setPreviewEnabled] = useState(
|
|
455
|
+
const [previewEnabled, setPreviewEnabled] = useState(() => readWorkspaceChrome().previewEnabled);
|
|
365
456
|
const [previewKey, setPreviewKey] = useState<string | number | null>(null);
|
|
366
457
|
const [tooltip, setTooltip] = useState<TooltipState | null>(null);
|
|
367
458
|
const [pageSize, setPageSize] = useState("15");
|
|
@@ -383,6 +474,10 @@ export function RecordWorkspace<T>({
|
|
|
383
474
|
setInternalVisibleKeys(readStoredColumnKeys(columnPrefsKey, fallbackKeys, allowedKeys));
|
|
384
475
|
}, [allowedKeys, columnPrefsKey, fallbackKeys, isControlled]);
|
|
385
476
|
|
|
477
|
+
useEffect(() => {
|
|
478
|
+
setFilters(readStoredFilters(filtersPrefsKey(columnPrefsKey), allowedKeys));
|
|
479
|
+
}, [allowedKeys, columnPrefsKey]);
|
|
480
|
+
|
|
386
481
|
const resolvedVisibleKeys = useMemo(() => {
|
|
387
482
|
const source = isControlled ? visibleColumnKeys! : internalVisibleKeys;
|
|
388
483
|
const filtered = source.filter((key) => allowedKeys.has(key));
|
|
@@ -565,15 +660,25 @@ export function RecordWorkspace<T>({
|
|
|
565
660
|
const previewTitle = previewItem && visibleColumns[0] ? cellText(visibleColumns[0], previewItem) : null;
|
|
566
661
|
|
|
567
662
|
function changeFilter(key: string, value: string) {
|
|
568
|
-
setFilters((current) =>
|
|
663
|
+
setFilters((current) => {
|
|
664
|
+
const next = { ...current, [key]: value };
|
|
665
|
+
writeStoredFilters(filterStorageKey, next);
|
|
666
|
+
return next;
|
|
667
|
+
});
|
|
569
668
|
setPage(1);
|
|
570
669
|
}
|
|
571
670
|
|
|
572
671
|
function clearFilters() {
|
|
573
672
|
setFilters({});
|
|
673
|
+
writeStoredFilters(filterStorageKey, {});
|
|
574
674
|
setPage(1);
|
|
575
675
|
}
|
|
576
676
|
|
|
677
|
+
function setSideOpenValue(open: boolean) {
|
|
678
|
+
setSideOpen(open);
|
|
679
|
+
writeWorkspaceChrome({ previewEnabled, sideOpen: open });
|
|
680
|
+
}
|
|
681
|
+
|
|
577
682
|
function toggleSort(column: TableColumn<T>) {
|
|
578
683
|
if (column.sortable === false) {
|
|
579
684
|
return;
|
|
@@ -592,6 +697,7 @@ export function RecordWorkspace<T>({
|
|
|
592
697
|
|
|
593
698
|
function setPreviewEnabledValue(enabled: boolean) {
|
|
594
699
|
setPreviewEnabled(enabled);
|
|
700
|
+
writeWorkspaceChrome({ previewEnabled: enabled, sideOpen });
|
|
595
701
|
setTooltip(null);
|
|
596
702
|
if (!enabled) {
|
|
597
703
|
setPreviewKey(null);
|
|
@@ -663,7 +769,7 @@ export function RecordWorkspace<T>({
|
|
|
663
769
|
title="Columns"
|
|
664
770
|
aria-label="Columns"
|
|
665
771
|
onClick={() => {
|
|
666
|
-
|
|
772
|
+
setSideOpenValue(true);
|
|
667
773
|
setColumnsOpen(true);
|
|
668
774
|
}}
|
|
669
775
|
>
|
|
@@ -679,7 +785,7 @@ export function RecordWorkspace<T>({
|
|
|
679
785
|
aria-label="Download"
|
|
680
786
|
disabled={downloadBusy}
|
|
681
787
|
onClick={() => {
|
|
682
|
-
|
|
788
|
+
setSideOpenValue(true);
|
|
683
789
|
setDownloadOpen(true);
|
|
684
790
|
}}
|
|
685
791
|
>
|
|
@@ -694,7 +800,7 @@ export function RecordWorkspace<T>({
|
|
|
694
800
|
aria-label="Bulk entry"
|
|
695
801
|
disabled={importBusy}
|
|
696
802
|
onClick={() => {
|
|
697
|
-
|
|
803
|
+
setSideOpenValue(true);
|
|
698
804
|
setBulkOpen(true);
|
|
699
805
|
}}
|
|
700
806
|
>
|
|
@@ -707,7 +813,7 @@ export function RecordWorkspace<T>({
|
|
|
707
813
|
className="ghost side-rail-icon"
|
|
708
814
|
title="Show filters"
|
|
709
815
|
aria-label="Show filters"
|
|
710
|
-
onClick={() =>
|
|
816
|
+
onClick={() => setSideOpenValue(true)}
|
|
711
817
|
>
|
|
712
818
|
<FilterIcon />
|
|
713
819
|
{activeFilterCount > 0 ? <span className="filter-badge">{activeFilterCount}</span> : null}
|
|
@@ -1158,7 +1264,7 @@ export function RecordWorkspace<T>({
|
|
|
1158
1264
|
className="ghost side-rail-toggle"
|
|
1159
1265
|
aria-expanded={sideOpen}
|
|
1160
1266
|
title={sideOpen ? "Collapse" : "Expand"}
|
|
1161
|
-
onClick={() =>
|
|
1267
|
+
onClick={() => setSideOpenValue(!sideOpen)}
|
|
1162
1268
|
>
|
|
1163
1269
|
<ChevronIcon open={sideOpen} />
|
|
1164
1270
|
{sideOpen ? <span>Collapse</span> : null}
|