tinybase 6.5.2 → 6.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,12 +3,12 @@ import {Fragment, jsx, jsxs} from 'react/jsx-runtime';
3
3
  import {
4
4
  CellView,
5
5
  ResultCellView,
6
- useCell,
6
+ useCell as useCell$1,
7
7
  useCreatePersister,
8
8
  useCreateStore,
9
+ useHasCell,
9
10
  useIndexes,
10
11
  useIndexesIds,
11
- useIndexesOrIndexesById,
12
12
  useIndexIds,
13
13
  useMetric,
14
14
  useMetricIds,
@@ -20,30 +20,21 @@ import {
20
20
  useRelationshipIds,
21
21
  useRelationships,
22
22
  useRelationshipsIds,
23
- useRelationshipsOrRelationshipsById,
24
- useRemoteRowId,
25
- useResultRowCount,
26
- useResultSortedRowIds,
27
- useResultTableCellIds,
28
- useRowCount,
29
- useRowIds,
30
- useSetCellCallback,
31
- useSetValueCallback,
23
+ useSetCellCallback as useSetCellCallback$1,
24
+ useSetValueCallback as useSetValueCallback$1,
32
25
  useSliceIds,
33
- useSliceRowIds,
34
- useSortedRowIds,
35
26
  useStore,
36
27
  useStoreIds,
37
- useStoreOrStoreById,
38
- useTableCellIds,
28
+ useTableCellIds as useTableCellIds$1,
39
29
  useTableIds,
40
- useValue,
41
- useValueIds,
30
+ useValue as useValue$1,
31
+ useValueIds as useValueIds$1,
42
32
  useValues,
43
33
  ValueView,
44
34
  } from '../ui-react/index.js';
45
35
 
46
36
  const getTypeOf = (thing) => typeof thing;
37
+ const TINYBASE = 'tinybase';
47
38
  const EMPTY_STRING = '';
48
39
  const DOT = '.';
49
40
  const STRING = getTypeOf(EMPTY_STRING);
@@ -53,8 +44,13 @@ const FUNCTION = getTypeOf(getTypeOf);
53
44
  const TYPE = 'type';
54
45
  const DEFAULT = 'default';
55
46
  const LISTENER = 'Listener';
47
+ const RESULT = 'Result';
48
+ const GET = 'get';
49
+ const SET = 'set';
56
50
  const ADD = 'add';
51
+ const DEL = 'del';
57
52
  const HAS = 'Has';
53
+ const _HAS = 'has';
58
54
  const IDS = 'Ids';
59
55
  const TABLE = 'Table';
60
56
  const TABLES = TABLE + 's';
@@ -62,13 +58,17 @@ const TABLE_IDS = TABLE + IDS;
62
58
  const ROW = 'Row';
63
59
  const ROW_COUNT = ROW + 'Count';
64
60
  const ROW_IDS = ROW + IDS;
61
+ const SORTED_ROW_IDS = 'Sorted' + ROW + IDS;
65
62
  const CELL = 'Cell';
66
63
  const CELL_IDS = CELL + IDS;
67
64
  const VALUE = 'Value';
68
65
  const VALUES = VALUE + 's';
69
66
  const VALUE_IDS = VALUE + IDS;
67
+ const SLICE = 'Slice';
68
+ const REMOTE_ROW_ID = 'Remote' + ROW + 'Id';
70
69
  const CURRENT_TARGET = 'currentTarget';
71
70
  const _VALUE = 'value';
71
+ const EXTRA = 'extra';
72
72
  const UNDEFINED = '\uFFFC';
73
73
  const id = (key) => EMPTY_STRING + key;
74
74
  const strSplit = (str, separator = EMPTY_STRING, limit) =>
@@ -91,6 +91,7 @@ const isArray = (thing) => Array.isArray(thing);
91
91
  const slice = (arrayOrString, start, end) => arrayOrString.slice(start, end);
92
92
  const size = (arrayOrString) => arrayOrString.length;
93
93
  const test = (regex, subject) => regex.test(subject);
94
+ const getUndefined = () => void 0;
94
95
  const errorNew = (message) => {
95
96
  throw new Error(message);
96
97
  };
@@ -114,6 +115,7 @@ const arrayJoin = (array, sep = EMPTY_STRING) => array.join(sep);
114
115
  const arrayMap = (array, cb) => array.map(cb);
115
116
  const arrayIsEmpty = (array) => size(array) == 0;
116
117
  const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);
118
+ const arrayFilter = (array, cb) => array.filter(cb);
117
119
  const arrayClear = (array, to) => array.splice(0, to);
118
120
  const arrayPush = (array, ...values) => array.push(...values);
119
121
  const arrayShift = (array) => array.shift();
@@ -136,6 +138,7 @@ const isObject = (obj) =>
136
138
  const objIds = object.keys;
137
139
  const objFreeze = object.freeze;
138
140
  const objNew = (entries = []) => object.fromEntries(entries);
141
+ const objGet = (obj, id) => ifNotUndefined(obj, (obj2) => obj2[id]);
139
142
  const objHas = (obj, id) => id in obj;
140
143
  const objDel = (obj, id) => {
141
144
  delete obj[id];
@@ -149,6 +152,19 @@ const objMap = (obj, cb) =>
149
152
  objNew(objToArray(obj, (value, id) => [id, cb(value, id)]));
150
153
  const objSize = (obj) => size(objIds(obj));
151
154
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
155
+ const objIsEqual = (obj1, obj2) => {
156
+ const entries1 = objEntries(obj1);
157
+ return (
158
+ size(entries1) === objSize(obj2) &&
159
+ arrayEvery(entries1, ([index, value1]) =>
160
+ isObject(value1)
161
+ ? isObject(obj2[index])
162
+ ? objIsEqual(obj2[index], value1)
163
+ : false
164
+ : obj2[index] === value1,
165
+ )
166
+ );
167
+ };
152
168
  const objValidate = (obj, validateChild, onInvalidObj, emptyIsValid = 0) => {
153
169
  if (
154
170
  isUndefined(obj) ||
@@ -654,7 +670,13 @@ const setOrDelCell = (store, tableId, rowId, cellId, cell) =>
654
670
  const setOrDelValue = (store, valueId, value) =>
655
671
  isUndefined(value) ? store.delValue(valueId) : store.setValue(valueId, value);
656
672
  const getTypeCase = (type, stringCase, numberCase, booleanCase) =>
657
- type == STRING ? stringCase : type == NUMBER ? numberCase : booleanCase;
673
+ type == STRING
674
+ ? stringCase
675
+ : type == NUMBER
676
+ ? numberCase
677
+ : type == BOOLEAN
678
+ ? booleanCase
679
+ : null;
658
680
 
659
681
  const defaultSorter = (sortKey1, sortKey2) =>
660
682
  (sortKey1 ?? 0) < (sortKey2 ?? 0) ? -1 : 1;
@@ -2056,7 +2078,7 @@ const EDITABLE_CELL = 'editable';
2056
2078
  const getUniqueId = (...args) => jsonStringWithMap(args);
2057
2079
  const sortedIdsMap = (ids, callback) => arrayMap(arraySort([...ids]), callback);
2058
2080
  const useEditable = (uniqueId, s) => [
2059
- !!useCell(STATE_TABLE, uniqueId, EDITABLE_CELL, s),
2081
+ !!useCell$1(STATE_TABLE, uniqueId, EDITABLE_CELL, s),
2060
2082
  useCallback(
2061
2083
  (event) => {
2062
2084
  s.setCell(STATE_TABLE, uniqueId, EDITABLE_CELL, (editable) => !editable);
@@ -2067,9 +2089,9 @@ const useEditable = (uniqueId, s) => [
2067
2089
  ];
2068
2090
 
2069
2091
  const Nub = ({s}) => {
2070
- const position = useValue(POSITION_VALUE, s) ?? 1;
2071
- const handleOpen = useSetValueCallback(OPEN_VALUE, () => true, [], s);
2072
- return useValue(OPEN_VALUE, s)
2092
+ const position = useValue$1(POSITION_VALUE, s) ?? 1;
2093
+ const handleOpen = useSetValueCallback$1(OPEN_VALUE, () => true, [], s);
2094
+ return useValue$1(OPEN_VALUE, s)
2073
2095
  ? null
2074
2096
  : /* @__PURE__ */ jsx('img', {
2075
2097
  onClick: handleOpen,
@@ -2078,13 +2100,373 @@ const Nub = ({s}) => {
2078
2100
  });
2079
2101
  };
2080
2102
 
2081
- const EDITABLE = 'editable';
2082
- const LEFT_ARROW = '\u2190';
2083
- const UP_ARROW = '\u2191';
2084
- const RIGHT_ARROW = '\u2192';
2085
- const DOWN_ARROW = '\u2193';
2086
- const useDottedCellIds = (tableId, store) =>
2087
- arrayMap(useTableCellIds(tableId, store), (cellId) => tableId + DOT + cellId);
2103
+ const TINYBASE_CONTEXT = TINYBASE + '_uirc';
2104
+ const Context = GLOBAL[TINYBASE_CONTEXT]
2105
+ ? /* istanbul ignore next */
2106
+ GLOBAL[TINYBASE_CONTEXT]
2107
+ : (GLOBAL[TINYBASE_CONTEXT] = createContext([]));
2108
+ const useThing = (id, offset) => {
2109
+ const contextValue = useContext(Context);
2110
+ return isUndefined(id)
2111
+ ? contextValue[offset * 2]
2112
+ : isString(id)
2113
+ ? objGet(contextValue[offset * 2 + 1], id)
2114
+ : id;
2115
+ };
2116
+ const useThingOrThingById = (thingOrThingId, offset) => {
2117
+ const thing = useThing(thingOrThingId, offset);
2118
+ return isUndefined(thingOrThingId) || isString(thingOrThingId)
2119
+ ? thing
2120
+ : thingOrThingId;
2121
+ };
2122
+
2123
+ const OFFSET_STORE = 0;
2124
+ const OFFSET_INDEXES = 2;
2125
+ const OFFSET_RELATIONSHIPS = 3;
2126
+ const OFFSET_QUERIES = 4;
2127
+
2128
+ const EMPTY_ARRAY = [];
2129
+ const DEFAULTS = [{}, [], [EMPTY_ARRAY, void 0, EMPTY_ARRAY], void 0, false, 0];
2130
+ const IS_EQUALS = [
2131
+ objIsEqual,
2132
+ arrayIsEqual,
2133
+ (
2134
+ [backwardIds1, currentId1, forwardIds1],
2135
+ [backwardIds2, currentId2, forwardIds2],
2136
+ ) =>
2137
+ currentId1 === currentId2 &&
2138
+ arrayIsEqual(backwardIds1, backwardIds2) &&
2139
+ arrayIsEqual(forwardIds1, forwardIds2),
2140
+ ];
2141
+ const isEqual = (thing1, thing2) => thing1 === thing2;
2142
+ const addAndDelListener = (thing, listenable, ...args) => {
2143
+ const listenerId = thing?.[ADD + listenable + LISTENER]?.(...args);
2144
+ return () => thing?.delListener?.(listenerId);
2145
+ };
2146
+ const useListenable = (listenable, thing, returnType, args = EMPTY_ARRAY) => {
2147
+ const lastResult = useRef(DEFAULTS[returnType]);
2148
+ const getResult = useCallback(
2149
+ () => {
2150
+ const nextResult =
2151
+ thing?.[(returnType == 4 /* Boolean */ ? _HAS : GET) + listenable]?.(
2152
+ ...args,
2153
+ ) ?? DEFAULTS[returnType];
2154
+ return !(IS_EQUALS[returnType] ?? isEqual)(nextResult, lastResult.current)
2155
+ ? (lastResult.current = nextResult)
2156
+ : lastResult.current;
2157
+ },
2158
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */
2159
+ [thing, returnType, listenable, ...args],
2160
+ );
2161
+ const subscribe = useCallback(
2162
+ (listener) =>
2163
+ addAndDelListener(
2164
+ thing,
2165
+ (returnType == 4 /* Boolean */ ? HAS : EMPTY_STRING) + listenable,
2166
+ ...args,
2167
+ listener,
2168
+ ),
2169
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */
2170
+ [thing, returnType, listenable, ...args],
2171
+ );
2172
+ return useSyncExternalStore(subscribe, getResult, getResult);
2173
+ };
2174
+ const useSetCallback = (
2175
+ storeOrStoreId,
2176
+ settable,
2177
+ get,
2178
+ getDeps = EMPTY_ARRAY,
2179
+ then = getUndefined,
2180
+ thenDeps = EMPTY_ARRAY,
2181
+ ...args
2182
+ ) => {
2183
+ const store = useStoreOrStoreById(storeOrStoreId);
2184
+ return useCallback(
2185
+ (parameter) =>
2186
+ ifNotUndefined(store, (store2) =>
2187
+ ifNotUndefined(get(parameter, store2), (thing) =>
2188
+ then(
2189
+ store2[SET + settable](
2190
+ ...argsOrGetArgs(args, store2, parameter),
2191
+ thing,
2192
+ ),
2193
+ thing,
2194
+ ),
2195
+ ),
2196
+ ),
2197
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2198
+ [store, settable, ...getDeps, ...thenDeps, ...nonFunctionDeps(args)],
2199
+ );
2200
+ };
2201
+ const argsOrGetArgs = (args, store, parameter) =>
2202
+ arrayMap(args, (arg) => (isFunction(arg) ? arg(parameter, store) : arg));
2203
+ const nonFunctionDeps = (args) => arrayFilter(args, (arg) => !isFunction(arg));
2204
+ const useDel = (
2205
+ storeOrStoreId,
2206
+ deletable,
2207
+ then = getUndefined,
2208
+ thenDeps = EMPTY_ARRAY,
2209
+ ...args
2210
+ ) => {
2211
+ const store = useStoreOrStoreById(storeOrStoreId);
2212
+ return useCallback(
2213
+ (parameter) =>
2214
+ then(store?.[DEL + deletable](...argsOrGetArgs(args, store, parameter))),
2215
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2216
+ [store, deletable, ...thenDeps, ...nonFunctionDeps(args)],
2217
+ );
2218
+ };
2219
+ const useSortedRowIdsImpl = (
2220
+ tableId,
2221
+ cellId,
2222
+ descending,
2223
+ offset,
2224
+ limit,
2225
+ storeOrStoreId,
2226
+ ) =>
2227
+ useListenable(
2228
+ SORTED_ROW_IDS,
2229
+ useStoreOrStoreById(storeOrStoreId),
2230
+ 1 /* Array */,
2231
+ [tableId, cellId, descending, offset, limit],
2232
+ );
2233
+ const useStoreOrStoreById = (storeOrStoreId) =>
2234
+ useThingOrThingById(storeOrStoreId, OFFSET_STORE);
2235
+ const useHasTables = (storeOrStoreId) =>
2236
+ useListenable(
2237
+ TABLES,
2238
+ useStoreOrStoreById(storeOrStoreId),
2239
+ 4 /* Boolean */,
2240
+ [],
2241
+ );
2242
+ const useTableCellIds = (tableId, storeOrStoreId) =>
2243
+ useListenable(
2244
+ TABLE + CELL_IDS,
2245
+ useStoreOrStoreById(storeOrStoreId),
2246
+ 1 /* Array */,
2247
+ [tableId],
2248
+ );
2249
+ const useRowCount = (tableId, storeOrStoreId) =>
2250
+ useListenable(
2251
+ ROW_COUNT,
2252
+ useStoreOrStoreById(storeOrStoreId),
2253
+ 5 /* Number */,
2254
+ [tableId],
2255
+ );
2256
+ const useRowIds = (tableId, storeOrStoreId) =>
2257
+ useListenable(ROW_IDS, useStoreOrStoreById(storeOrStoreId), 1 /* Array */, [
2258
+ tableId,
2259
+ ]);
2260
+ const useSortedRowIds = (
2261
+ tableIdOrArgs,
2262
+ cellIdOrStoreOrStoreId,
2263
+ descending,
2264
+ offset,
2265
+ limit,
2266
+ storeOrStoreId,
2267
+ ) =>
2268
+ useSortedRowIdsImpl(
2269
+ ...(isObject(tableIdOrArgs)
2270
+ ? [
2271
+ tableIdOrArgs.tableId,
2272
+ tableIdOrArgs.cellId,
2273
+ tableIdOrArgs.descending ?? false,
2274
+ tableIdOrArgs.offset ?? 0,
2275
+ tableIdOrArgs.limit,
2276
+ cellIdOrStoreOrStoreId,
2277
+ ]
2278
+ : [
2279
+ tableIdOrArgs,
2280
+ cellIdOrStoreOrStoreId,
2281
+ descending,
2282
+ offset,
2283
+ limit,
2284
+ storeOrStoreId,
2285
+ ]),
2286
+ );
2287
+ const useCell = (tableId, rowId, cellId, storeOrStoreId) =>
2288
+ useListenable(
2289
+ CELL,
2290
+ useStoreOrStoreById(storeOrStoreId),
2291
+ 3 /* CellOrValue */,
2292
+ [tableId, rowId, cellId],
2293
+ );
2294
+ const useHasValues = (storeOrStoreId) =>
2295
+ useListenable(
2296
+ VALUES,
2297
+ useStoreOrStoreById(storeOrStoreId),
2298
+ 4 /* Boolean */,
2299
+ [],
2300
+ );
2301
+ const useValueIds = (storeOrStoreId) =>
2302
+ useListenable(VALUE_IDS, useStoreOrStoreById(storeOrStoreId), 1 /* Array */);
2303
+ const useValue = (valueId, storeOrStoreId) =>
2304
+ useListenable(
2305
+ VALUE,
2306
+ useStoreOrStoreById(storeOrStoreId),
2307
+ 3 /* CellOrValue */,
2308
+ [valueId],
2309
+ );
2310
+ const useSetTableCallback = (
2311
+ tableId,
2312
+ getTable,
2313
+ getTableDeps,
2314
+ storeOrStoreId,
2315
+ then,
2316
+ thenDeps,
2317
+ ) =>
2318
+ useSetCallback(
2319
+ storeOrStoreId,
2320
+ TABLE,
2321
+ getTable,
2322
+ getTableDeps,
2323
+ then,
2324
+ thenDeps,
2325
+ tableId,
2326
+ );
2327
+ const useSetRowCallback = (
2328
+ tableId,
2329
+ rowId,
2330
+ getRow,
2331
+ getRowDeps,
2332
+ storeOrStoreId,
2333
+ then,
2334
+ thenDeps,
2335
+ ) =>
2336
+ useSetCallback(
2337
+ storeOrStoreId,
2338
+ ROW,
2339
+ getRow,
2340
+ getRowDeps,
2341
+ then,
2342
+ thenDeps,
2343
+ tableId,
2344
+ rowId,
2345
+ );
2346
+ const useSetCellCallback = (
2347
+ tableId,
2348
+ rowId,
2349
+ cellId,
2350
+ getCell,
2351
+ getCellDeps,
2352
+ storeOrStoreId,
2353
+ then,
2354
+ thenDeps,
2355
+ ) =>
2356
+ useSetCallback(
2357
+ storeOrStoreId,
2358
+ CELL,
2359
+ getCell,
2360
+ getCellDeps,
2361
+ then,
2362
+ thenDeps,
2363
+ tableId,
2364
+ rowId,
2365
+ cellId,
2366
+ );
2367
+ const useSetValueCallback = (
2368
+ valueId,
2369
+ getValue,
2370
+ getValueDeps,
2371
+ storeOrStoreId,
2372
+ then,
2373
+ thenDeps,
2374
+ ) =>
2375
+ useSetCallback(
2376
+ storeOrStoreId,
2377
+ VALUE,
2378
+ getValue,
2379
+ getValueDeps,
2380
+ then,
2381
+ thenDeps,
2382
+ valueId,
2383
+ );
2384
+ const useDelTablesCallback = (storeOrStoreId, then, thenDeps) =>
2385
+ useDel(storeOrStoreId, TABLES, then, thenDeps);
2386
+ const useDelTableCallback = (tableId, storeOrStoreId, then, thenDeps) =>
2387
+ useDel(storeOrStoreId, TABLE, then, thenDeps, tableId);
2388
+ const useDelRowCallback = (tableId, rowId, storeOrStoreId, then, thenDeps) =>
2389
+ useDel(storeOrStoreId, ROW, then, thenDeps, tableId, rowId);
2390
+ const useDelCellCallback = (
2391
+ tableId,
2392
+ rowId,
2393
+ cellId,
2394
+ forceDel,
2395
+ storeOrStoreId,
2396
+ then,
2397
+ thenDeps,
2398
+ ) =>
2399
+ useDel(
2400
+ storeOrStoreId,
2401
+ CELL,
2402
+ then,
2403
+ thenDeps,
2404
+ tableId,
2405
+ rowId,
2406
+ cellId,
2407
+ forceDel,
2408
+ );
2409
+ const useDelValuesCallback = (storeOrStoreId, then, thenDeps) =>
2410
+ useDel(storeOrStoreId, VALUES, then, thenDeps);
2411
+ const useDelValueCallback = (valueId, storeOrStoreId, then, thenDeps) =>
2412
+ useDel(storeOrStoreId, VALUE, then, thenDeps, valueId);
2413
+ const useIndexesOrIndexesById = (indexesOrIndexesId) =>
2414
+ useThingOrThingById(indexesOrIndexesId, OFFSET_INDEXES);
2415
+ const useSliceRowIds = (indexId, sliceId, indexesOrIndexesId) =>
2416
+ useListenable(
2417
+ SLICE + ROW_IDS,
2418
+ useIndexesOrIndexesById(indexesOrIndexesId),
2419
+ 1 /* Array */,
2420
+ [indexId, sliceId],
2421
+ );
2422
+ const useRelationshipsOrRelationshipsById = (relationshipsOrRelationshipsId) =>
2423
+ useThingOrThingById(relationshipsOrRelationshipsId, OFFSET_RELATIONSHIPS);
2424
+ const useRemoteRowId = (
2425
+ relationshipId,
2426
+ localRowId,
2427
+ relationshipsOrRelationshipsId,
2428
+ ) =>
2429
+ useListenable(
2430
+ REMOTE_ROW_ID,
2431
+ useRelationshipsOrRelationshipsById(relationshipsOrRelationshipsId),
2432
+ 3 /* CellOrValue */,
2433
+ [relationshipId, localRowId],
2434
+ );
2435
+ const useQueriesOrQueriesById = (queriesOrQueriesId) =>
2436
+ useThingOrThingById(queriesOrQueriesId, OFFSET_QUERIES);
2437
+ const useResultTableCellIds = (queryId, queriesOrQueriesId) =>
2438
+ useListenable(
2439
+ RESULT + TABLE + CELL_IDS,
2440
+ useQueriesOrQueriesById(queriesOrQueriesId),
2441
+ 1 /* Array */,
2442
+ [queryId],
2443
+ );
2444
+ const useResultRowCount = (queryId, queriesOrQueriesId) =>
2445
+ useListenable(
2446
+ RESULT + ROW_COUNT,
2447
+ useQueriesOrQueriesById(queriesOrQueriesId),
2448
+ 5 /* Number */,
2449
+ [queryId],
2450
+ );
2451
+ const useResultSortedRowIds = (
2452
+ queryId,
2453
+ cellId,
2454
+ descending,
2455
+ offset = 0,
2456
+ limit,
2457
+ queriesOrQueriesId,
2458
+ ) =>
2459
+ useListenable(
2460
+ RESULT + SORTED_ROW_IDS,
2461
+ useQueriesOrQueriesById(queriesOrQueriesId),
2462
+ 1 /* Array */,
2463
+ [queryId, cellId, descending, offset, limit],
2464
+ );
2465
+
2466
+ const useStoreCellComponentProps = (store, tableId) =>
2467
+ useMemo(() => ({store, tableId}), [store, tableId]);
2468
+ const useQueriesCellComponentProps = (queries, queryId) =>
2469
+ useMemo(() => ({queries, queryId}), [queries, queryId]);
2088
2470
  const useCallbackOrUndefined = (callback, deps, test) => {
2089
2471
  const returnCallback = useCallback(callback, deps);
2090
2472
  return test ? returnCallback : void 0;
@@ -2095,69 +2477,6 @@ const useParams = (...args) =>
2095
2477
  // eslint-disable-next-line react-hooks/exhaustive-deps
2096
2478
  args,
2097
2479
  );
2098
- const useStoreCellComponentProps = (store, tableId) =>
2099
- useMemo(() => ({store, tableId}), [store, tableId]);
2100
- const useQueriesCellComponentProps = (queries, queryId) =>
2101
- useMemo(() => ({queries, queryId}), [queries, queryId]);
2102
- const useSortingAndPagination = (
2103
- cellId,
2104
- descending = false,
2105
- sortOnClick,
2106
- offset = 0,
2107
- limit,
2108
- total,
2109
- paginator,
2110
- onChange,
2111
- ) => {
2112
- const [[currentCellId, currentDescending, currentOffset], setState] =
2113
- useState([cellId, descending, offset]);
2114
- const setStateAndChange = useCallback(
2115
- (sortAndOffset) => {
2116
- setState(sortAndOffset);
2117
- onChange?.(sortAndOffset);
2118
- },
2119
- [onChange],
2120
- );
2121
- const handleSort = useCallbackOrUndefined(
2122
- (cellId2) =>
2123
- setStateAndChange([
2124
- cellId2,
2125
- cellId2 == currentCellId ? !currentDescending : false,
2126
- currentOffset,
2127
- ]),
2128
- [setStateAndChange, currentCellId, currentDescending, currentOffset],
2129
- sortOnClick,
2130
- );
2131
- const handleChangeOffset = useCallback(
2132
- (offset2) => setStateAndChange([currentCellId, currentDescending, offset2]),
2133
- [setStateAndChange, currentCellId, currentDescending],
2134
- );
2135
- const PaginatorComponent =
2136
- paginator === true ? SortedTablePaginator : paginator;
2137
- return [
2138
- [currentCellId, currentDescending, currentOffset],
2139
- handleSort,
2140
- useMemo(
2141
- () =>
2142
- paginator === false
2143
- ? null
2144
- : /* @__PURE__ */ jsx(PaginatorComponent, {
2145
- offset: currentOffset,
2146
- limit,
2147
- total,
2148
- onChange: handleChangeOffset,
2149
- }),
2150
- [
2151
- paginator,
2152
- PaginatorComponent,
2153
- currentOffset,
2154
- limit,
2155
- total,
2156
- handleChangeOffset,
2157
- ],
2158
- ),
2159
- ];
2160
- };
2161
2480
  const useCells = (defaultCellIds, customCells, defaultCellComponent) =>
2162
2481
  useMemo(() => {
2163
2482
  const cellIds = customCells ?? defaultCellIds;
@@ -2173,6 +2492,54 @@ const useCells = (defaultCellIds, customCells, defaultCellComponent) =>
2173
2492
  }),
2174
2493
  );
2175
2494
  }, [customCells, defaultCellComponent, defaultCellIds]);
2495
+
2496
+ const UP_ARROW = '\u2191';
2497
+ const DOWN_ARROW = '\u2193';
2498
+ const EDITABLE = 'editable';
2499
+ const extraRowCells = (extraRowCells2 = [], extraRowCellProps, after = 0) =>
2500
+ arrayMap(extraRowCells2, ({component: Component}, index) =>
2501
+ /* @__PURE__ */ jsx(
2502
+ 'td',
2503
+ {
2504
+ className: EXTRA,
2505
+ children: /* @__PURE__ */ jsx(Component, {...extraRowCellProps}),
2506
+ },
2507
+ extraKey(index, after),
2508
+ ),
2509
+ );
2510
+ const extraKey = (index, after) => (after ? '>' : '<') + index;
2511
+ const extraHeaders = (extraCells = [], after = 0) =>
2512
+ arrayMap(extraCells, ({label}, index) =>
2513
+ /* @__PURE__ */ jsx(
2514
+ 'th',
2515
+ {className: EXTRA, children: label},
2516
+ extraKey(index, after),
2517
+ ),
2518
+ );
2519
+
2520
+ const HtmlHeaderCell = ({
2521
+ cellId,
2522
+ sort: [sortCellId, sortDescending],
2523
+ label = cellId ?? EMPTY_STRING,
2524
+ onClick,
2525
+ }) =>
2526
+ /* @__PURE__ */ jsxs('th', {
2527
+ onClick: useCallbackOrUndefined(
2528
+ () => onClick?.(cellId),
2529
+ [onClick, cellId],
2530
+ onClick,
2531
+ ),
2532
+ className:
2533
+ isUndefined(sortDescending) || sortCellId != cellId
2534
+ ? void 0
2535
+ : `sorted ${sortDescending ? 'de' : 'a'}scending`,
2536
+ children: [
2537
+ isUndefined(sortDescending) || sortCellId != cellId
2538
+ ? null
2539
+ : (sortDescending ? DOWN_ARROW : UP_ARROW) + ' ',
2540
+ label,
2541
+ ],
2542
+ });
2176
2543
  const HtmlTable = ({
2177
2544
  className,
2178
2545
  headerRow,
@@ -2181,6 +2548,8 @@ const HtmlTable = ({
2181
2548
  cells,
2182
2549
  cellComponentProps,
2183
2550
  rowIds,
2551
+ extraCellsBefore,
2552
+ extraCellsAfter,
2184
2553
  sortAndOffset,
2185
2554
  handleSort,
2186
2555
  paginatorComponent,
@@ -2197,6 +2566,7 @@ const HtmlTable = ({
2197
2566
  : /* @__PURE__ */ jsx('thead', {
2198
2567
  children: /* @__PURE__ */ jsxs('tr', {
2199
2568
  children: [
2569
+ extraHeaders(extraCellsBefore),
2200
2570
  idColumn === false
2201
2571
  ? null
2202
2572
  : /* @__PURE__ */ jsx(HtmlHeaderCell, {
@@ -2216,124 +2586,51 @@ const HtmlTable = ({
2216
2586
  cellId,
2217
2587
  ),
2218
2588
  ),
2589
+ extraHeaders(extraCellsAfter, 1),
2219
2590
  ],
2220
2591
  }),
2221
2592
  }),
2222
2593
  /* @__PURE__ */ jsx('tbody', {
2223
- children: arrayMap(rowIds, (rowId) =>
2224
- /* @__PURE__ */ jsxs(
2594
+ children: arrayMap(rowIds, (rowId) => {
2595
+ const rowProps = {...cellComponentProps, rowId};
2596
+ return /* @__PURE__ */ jsxs(
2225
2597
  'tr',
2226
2598
  {
2227
2599
  children: [
2600
+ extraRowCells(extraCellsBefore, rowProps),
2228
2601
  idColumn === false
2229
2602
  ? null
2230
- : /* @__PURE__ */ jsx('th', {children: rowId}),
2603
+ : /* @__PURE__ */ jsx('th', {title: rowId, children: rowId}),
2231
2604
  objToArray(
2232
2605
  cells,
2233
- ({component: CellView2, getComponentProps}, cellId) =>
2606
+ ({component: CellView, getComponentProps}, cellId) =>
2234
2607
  /* @__PURE__ */ jsx(
2235
2608
  'td',
2236
2609
  {
2237
- children: /* @__PURE__ */ jsx(CellView2, {
2610
+ children: /* @__PURE__ */ jsx(CellView, {
2238
2611
  ...getProps(getComponentProps, rowId, cellId),
2239
- ...cellComponentProps,
2240
- rowId,
2612
+ ...rowProps,
2241
2613
  cellId,
2242
2614
  }),
2243
2615
  },
2244
2616
  cellId,
2245
2617
  ),
2246
2618
  ),
2619
+ extraRowCells(extraCellsAfter, rowProps, 1),
2247
2620
  ],
2248
2621
  },
2249
2622
  rowId,
2250
- ),
2251
- ),
2623
+ );
2624
+ }),
2252
2625
  }),
2253
2626
  ],
2254
2627
  });
2255
- const HtmlHeaderCell = ({
2256
- cellId,
2257
- sort: [sortCellId, sortDescending],
2258
- label = cellId ?? EMPTY_STRING,
2259
- onClick,
2260
- }) =>
2261
- /* @__PURE__ */ jsxs('th', {
2262
- onClick: useCallbackOrUndefined(
2263
- () => onClick?.(cellId),
2264
- [onClick, cellId],
2265
- onClick,
2266
- ),
2267
- className:
2268
- isUndefined(sortDescending) || sortCellId != cellId
2269
- ? void 0
2270
- : `sorted ${sortDescending ? 'de' : 'a'}scending`,
2271
- children: [
2272
- isUndefined(sortDescending) || sortCellId != cellId
2273
- ? null
2274
- : (sortDescending ? DOWN_ARROW : UP_ARROW) + ' ',
2275
- label,
2276
- ],
2277
- });
2278
- const RelationshipInHtmlRow = ({
2279
- localRowId,
2280
- params: [
2281
- idColumn,
2282
- cells,
2283
- localTableId,
2284
- remoteTableId,
2285
- relationshipId,
2286
- relationships,
2287
- store,
2288
- ],
2289
- }) => {
2290
- const remoteRowId = useRemoteRowId(relationshipId, localRowId, relationships);
2291
- return /* @__PURE__ */ jsxs('tr', {
2292
- children: [
2293
- idColumn === false
2294
- ? null
2295
- : /* @__PURE__ */ jsxs(Fragment, {
2296
- children: [
2297
- /* @__PURE__ */ jsx('th', {children: localRowId}),
2298
- /* @__PURE__ */ jsx('th', {children: remoteRowId}),
2299
- ],
2300
- }),
2301
- objToArray(
2302
- cells,
2303
- ({component: CellView2, getComponentProps}, compoundCellId) => {
2304
- const [tableId, cellId] = strSplit(compoundCellId, DOT, 2);
2305
- const rowId =
2306
- tableId === localTableId
2307
- ? localRowId
2308
- : tableId === remoteTableId
2309
- ? remoteRowId
2310
- : null;
2311
- return isUndefined(rowId)
2312
- ? null
2313
- : /* @__PURE__ */ jsx(
2314
- 'td',
2315
- {
2316
- children: /* @__PURE__ */ jsx(CellView2, {
2317
- ...getProps(getComponentProps, rowId, cellId),
2318
- store,
2319
- tableId,
2320
- rowId,
2321
- cellId,
2322
- }),
2323
- },
2324
- compoundCellId,
2325
- );
2326
- },
2327
- ),
2328
- ],
2329
- });
2330
- };
2331
- const EditableThing = ({
2332
- thing,
2333
- onThingChange,
2334
- className,
2335
- hasSchema,
2336
- showType = true,
2628
+ const EditableThing = ({
2629
+ thing,
2630
+ onThingChange,
2631
+ className,
2632
+ hasSchema,
2633
+ showType = true,
2337
2634
  }) => {
2338
2635
  const [thingType, setThingType] = useState();
2339
2636
  const [currentThing, setCurrentThing] = useState();
@@ -2376,181 +2673,172 @@ const EditableThing = ({
2376
2673
  booleanThing,
2377
2674
  thingType,
2378
2675
  ]);
2676
+ const widget = getTypeCase(
2677
+ thingType,
2678
+ /* @__PURE__ */ jsx(
2679
+ 'input',
2680
+ {
2681
+ value: stringThing,
2682
+ onChange: useCallback(
2683
+ (event) =>
2684
+ handleThingChange(
2685
+ String(event[CURRENT_TARGET][_VALUE]),
2686
+ setStringThing,
2687
+ ),
2688
+ [handleThingChange],
2689
+ ),
2690
+ },
2691
+ thingType,
2692
+ ),
2693
+ /* @__PURE__ */ jsx(
2694
+ 'input',
2695
+ {
2696
+ type: 'number',
2697
+ value: numberThing,
2698
+ onChange: useCallback(
2699
+ (event) =>
2700
+ handleThingChange(
2701
+ Number(event[CURRENT_TARGET][_VALUE] || 0),
2702
+ setNumberThing,
2703
+ ),
2704
+ [handleThingChange],
2705
+ ),
2706
+ },
2707
+ thingType,
2708
+ ),
2709
+ /* @__PURE__ */ jsx(
2710
+ 'input',
2711
+ {
2712
+ type: 'checkbox',
2713
+ checked: booleanThing,
2714
+ onChange: useCallback(
2715
+ (event) =>
2716
+ handleThingChange(
2717
+ Boolean(event[CURRENT_TARGET].checked),
2718
+ setBooleanThing,
2719
+ ),
2720
+ [handleThingChange],
2721
+ ),
2722
+ },
2723
+ thingType,
2724
+ ),
2725
+ );
2379
2726
  return /* @__PURE__ */ jsxs('div', {
2380
2727
  className,
2381
2728
  children: [
2382
- showType
2729
+ showType && widget
2383
2730
  ? /* @__PURE__ */ jsx('button', {
2731
+ title: thingType,
2384
2732
  className: thingType,
2385
2733
  onClick: handleTypeChange,
2386
2734
  children: thingType,
2387
2735
  })
2388
2736
  : null,
2389
- getTypeCase(
2390
- thingType,
2391
- /* @__PURE__ */ jsx(
2392
- 'input',
2393
- {
2394
- value: stringThing,
2395
- onChange: useCallback(
2396
- (event) =>
2397
- handleThingChange(
2398
- String(event[CURRENT_TARGET][_VALUE]),
2399
- setStringThing,
2400
- ),
2401
- [handleThingChange],
2402
- ),
2403
- },
2404
- thingType,
2405
- ),
2406
- /* @__PURE__ */ jsx(
2407
- 'input',
2408
- {
2409
- type: 'number',
2410
- value: numberThing,
2411
- onChange: useCallback(
2412
- (event) =>
2413
- handleThingChange(
2414
- Number(event[CURRENT_TARGET][_VALUE] || 0),
2415
- setNumberThing,
2416
- ),
2417
- [handleThingChange],
2418
- ),
2419
- },
2420
- thingType,
2421
- ),
2422
- /* @__PURE__ */ jsx(
2423
- 'input',
2424
- {
2425
- type: 'checkbox',
2426
- checked: booleanThing,
2427
- onChange: useCallback(
2428
- (event) =>
2429
- handleThingChange(
2430
- Boolean(event[CURRENT_TARGET].checked),
2431
- setBooleanThing,
2432
- ),
2433
- [handleThingChange],
2434
- ),
2435
- },
2436
- thingType,
2437
- ),
2438
- ),
2737
+ widget,
2439
2738
  ],
2440
2739
  });
2441
2740
  };
2442
- const SortedTableInHtmlTable = ({
2741
+
2742
+ const EditableCellView = ({
2443
2743
  tableId,
2744
+ rowId,
2444
2745
  cellId,
2445
- descending,
2446
- offset,
2447
- limit,
2448
2746
  store,
2449
- editable,
2450
- sortOnClick,
2451
- paginator = false,
2452
- onChange,
2453
- customCells,
2454
- ...props
2455
- }) => {
2456
- const [sortAndOffset, handleSort, paginatorComponent] =
2457
- useSortingAndPagination(
2747
+ className,
2748
+ showType,
2749
+ }) =>
2750
+ /* @__PURE__ */ jsx(EditableThing, {
2751
+ thing: useCell(tableId, rowId, cellId, store),
2752
+ onThingChange: useSetCellCallback(
2753
+ tableId,
2754
+ rowId,
2458
2755
  cellId,
2459
- descending,
2460
- sortOnClick,
2461
- offset,
2462
- limit,
2463
- useRowCount(tableId, store),
2464
- paginator,
2465
- onChange,
2466
- );
2467
- return /* @__PURE__ */ jsx(HtmlTable, {
2468
- ...props,
2469
- params: useParams(
2470
- useCells(
2471
- useTableCellIds(tableId, store),
2472
- customCells,
2473
- editable ? EditableCellView : CellView,
2474
- ),
2475
- useStoreCellComponentProps(store, tableId),
2476
- useSortedRowIds(tableId, ...sortAndOffset, limit, store),
2477
- sortAndOffset,
2478
- handleSort,
2479
- paginatorComponent,
2756
+ (cell) => cell,
2757
+ [],
2758
+ store,
2480
2759
  ),
2760
+ className: className ?? EDITABLE + CELL,
2761
+ showType,
2762
+ hasSchema: useStoreOrStoreById(store)?.hasTablesSchema,
2481
2763
  });
2482
- };
2483
- const ValuesInHtmlTable = ({
2484
- store,
2485
- editable = false,
2486
- valueComponent: Value = editable ? EditableValueView : ValueView,
2487
- getValueComponentProps,
2488
- className,
2489
- headerRow,
2490
- idColumn,
2491
- }) =>
2492
- /* @__PURE__ */ jsxs('table', {
2493
- className,
2764
+
2765
+ const EditableValueView = ({valueId, store, className, showType}) =>
2766
+ /* @__PURE__ */ jsx(EditableThing, {
2767
+ thing: useValue(valueId, store),
2768
+ onThingChange: useSetValueCallback(valueId, (value) => value, [], store),
2769
+ className: className ?? EDITABLE + VALUE,
2770
+ showType,
2771
+ hasSchema: useStoreOrStoreById(store)?.hasValuesSchema,
2772
+ });
2773
+
2774
+ const useDottedCellIds = (tableId, store) =>
2775
+ arrayMap(useTableCellIds(tableId, store), (cellId) => tableId + DOT + cellId);
2776
+ const RelationshipInHtmlRow = ({
2777
+ localRowId,
2778
+ params: [
2779
+ idColumn,
2780
+ cells,
2781
+ localTableId,
2782
+ remoteTableId,
2783
+ relationshipId,
2784
+ relationships,
2785
+ store,
2786
+ extraCellsBefore,
2787
+ extraCellsAfter,
2788
+ ],
2789
+ }) => {
2790
+ const remoteRowId = useRemoteRowId(relationshipId, localRowId, relationships);
2791
+ const rowProps = {
2792
+ tableId: localTableId ?? '',
2793
+ rowId: localRowId,
2794
+ store,
2795
+ };
2796
+ return /* @__PURE__ */ jsxs('tr', {
2494
2797
  children: [
2495
- headerRow === false
2798
+ extraRowCells(extraCellsBefore, rowProps),
2799
+ idColumn === false
2496
2800
  ? null
2497
- : /* @__PURE__ */ jsx('thead', {
2498
- children: /* @__PURE__ */ jsxs('tr', {
2499
- children: [
2500
- idColumn === false
2501
- ? null
2502
- : /* @__PURE__ */ jsx('th', {children: 'Id'}),
2503
- /* @__PURE__ */ jsx('th', {children: VALUE}),
2504
- ],
2505
- }),
2801
+ : /* @__PURE__ */ jsxs(Fragment, {
2802
+ children: [
2803
+ /* @__PURE__ */ jsx('th', {
2804
+ title: localRowId,
2805
+ children: localRowId,
2806
+ }),
2807
+ /* @__PURE__ */ jsx('th', {
2808
+ title: remoteRowId,
2809
+ children: remoteRowId,
2810
+ }),
2811
+ ],
2506
2812
  }),
2507
- /* @__PURE__ */ jsx('tbody', {
2508
- children: arrayMap(useValueIds(store), (valueId) =>
2509
- /* @__PURE__ */ jsxs(
2510
- 'tr',
2511
- {
2512
- children: [
2513
- idColumn === false
2514
- ? null
2515
- : /* @__PURE__ */ jsx('th', {children: valueId}),
2516
- /* @__PURE__ */ jsx('td', {
2517
- children: /* @__PURE__ */ jsx(Value, {
2518
- ...getProps(getValueComponentProps, valueId),
2519
- valueId,
2813
+ objToArray(
2814
+ cells,
2815
+ ({component: CellView2, getComponentProps}, compoundCellId) => {
2816
+ const [tableId, cellId] = strSplit(compoundCellId, DOT, 2);
2817
+ const rowId =
2818
+ tableId === localTableId
2819
+ ? localRowId
2820
+ : tableId === remoteTableId
2821
+ ? remoteRowId
2822
+ : null;
2823
+ return isUndefined(rowId)
2824
+ ? null
2825
+ : /* @__PURE__ */ jsx(
2826
+ 'td',
2827
+ {
2828
+ children: /* @__PURE__ */ jsx(CellView2, {
2829
+ ...getProps(getComponentProps, rowId, cellId),
2520
2830
  store,
2831
+ tableId,
2832
+ rowId,
2833
+ cellId,
2521
2834
  }),
2522
- }),
2523
- ],
2524
- },
2525
- valueId,
2526
- ),
2527
- ),
2528
- }),
2529
- ],
2530
- });
2531
- const SliceInHtmlTable = ({
2532
- indexId,
2533
- sliceId,
2534
- indexes,
2535
- editable,
2536
- customCells,
2537
- ...props
2538
- }) => {
2539
- const [resolvedIndexes, store, tableId] = getIndexStoreTableId(
2540
- useIndexesOrIndexesById(indexes),
2541
- indexId,
2542
- );
2543
- return /* @__PURE__ */ jsx(HtmlTable, {
2544
- ...props,
2545
- params: useParams(
2546
- useCells(
2547
- useTableCellIds(tableId, store),
2548
- customCells,
2549
- editable ? EditableCellView : CellView,
2835
+ },
2836
+ compoundCellId,
2837
+ );
2838
+ },
2550
2839
  ),
2551
- useStoreCellComponentProps(store, tableId),
2552
- useSliceRowIds(indexId, sliceId, resolvedIndexes),
2553
- ),
2840
+ extraRowCells(extraCellsAfter, rowProps, 1),
2841
+ ],
2554
2842
  });
2555
2843
  };
2556
2844
  const RelationshipInHtmlTable = ({
@@ -2558,6 +2846,8 @@ const RelationshipInHtmlTable = ({
2558
2846
  relationships,
2559
2847
  editable,
2560
2848
  customCells,
2849
+ extraCellsBefore,
2850
+ extraCellsAfter,
2561
2851
  className,
2562
2852
  headerRow,
2563
2853
  idColumn = true,
@@ -2583,6 +2873,8 @@ const RelationshipInHtmlTable = ({
2583
2873
  relationshipId,
2584
2874
  resolvedRelationships,
2585
2875
  store,
2876
+ extraCellsBefore,
2877
+ extraCellsAfter,
2586
2878
  );
2587
2879
  return /* @__PURE__ */ jsxs('table', {
2588
2880
  className,
@@ -2592,6 +2884,7 @@ const RelationshipInHtmlTable = ({
2592
2884
  : /* @__PURE__ */ jsx('thead', {
2593
2885
  children: /* @__PURE__ */ jsxs('tr', {
2594
2886
  children: [
2887
+ extraHeaders(extraCellsBefore),
2595
2888
  idColumn === false
2596
2889
  ? null
2597
2890
  : /* @__PURE__ */ jsxs(Fragment, {
@@ -2607,6 +2900,7 @@ const RelationshipInHtmlTable = ({
2607
2900
  objToArray(cells, ({label}, cellId) =>
2608
2901
  /* @__PURE__ */ jsx('th', {children: label}, cellId),
2609
2902
  ),
2903
+ extraHeaders(extraCellsAfter, 1),
2610
2904
  ],
2611
2905
  }),
2612
2906
  }),
@@ -2625,76 +2919,68 @@ const RelationshipInHtmlTable = ({
2625
2919
  ],
2626
2920
  });
2627
2921
  };
2628
- const ResultSortedTableInHtmlTable = ({
2629
- queryId,
2922
+
2923
+ const LEFT_ARROW = '\u2190';
2924
+ const RIGHT_ARROW = '\u2192';
2925
+ const useSortingAndPagination = (
2630
2926
  cellId,
2631
- descending,
2632
- offset,
2633
- limit,
2634
- queries,
2927
+ descending = false,
2635
2928
  sortOnClick,
2636
- paginator = false,
2637
- customCells,
2929
+ offset = 0,
2930
+ limit,
2931
+ total,
2932
+ paginator,
2638
2933
  onChange,
2639
- ...props
2640
- }) => {
2641
- const [sortAndOffset, handleSort, paginatorComponent] =
2642
- useSortingAndPagination(
2643
- cellId,
2644
- descending,
2645
- sortOnClick,
2646
- offset,
2647
- limit,
2648
- useResultRowCount(queryId, queries),
2649
- paginator,
2650
- onChange,
2651
- );
2652
- return /* @__PURE__ */ jsx(HtmlTable, {
2653
- ...props,
2654
- params: useParams(
2655
- useCells(
2656
- useResultTableCellIds(queryId, queries),
2657
- customCells,
2658
- ResultCellView,
2659
- ),
2660
- useQueriesCellComponentProps(queries, queryId),
2661
- useResultSortedRowIds(queryId, ...sortAndOffset, limit, queries),
2662
- sortAndOffset,
2663
- handleSort,
2664
- paginatorComponent,
2934
+ ) => {
2935
+ const [[currentCellId, currentDescending, currentOffset], setState] =
2936
+ useState([cellId, descending, offset]);
2937
+ const setStateAndChange = useCallback(
2938
+ (sortAndOffset) => {
2939
+ setState(sortAndOffset);
2940
+ onChange?.(sortAndOffset);
2941
+ },
2942
+ [onChange],
2943
+ );
2944
+ const handleSort = useCallbackOrUndefined(
2945
+ (cellId2) =>
2946
+ setStateAndChange([
2947
+ cellId2,
2948
+ cellId2 == currentCellId ? !currentDescending : false,
2949
+ currentOffset,
2950
+ ]),
2951
+ [setStateAndChange, currentCellId, currentDescending, currentOffset],
2952
+ sortOnClick,
2953
+ );
2954
+ const handleChangeOffset = useCallback(
2955
+ (offset2) => setStateAndChange([currentCellId, currentDescending, offset2]),
2956
+ [setStateAndChange, currentCellId, currentDescending],
2957
+ );
2958
+ const PaginatorComponent =
2959
+ paginator === true ? SortedTablePaginator : paginator;
2960
+ return [
2961
+ [currentCellId, currentDescending, currentOffset],
2962
+ handleSort,
2963
+ useMemo(
2964
+ () =>
2965
+ paginator === false
2966
+ ? null
2967
+ : /* @__PURE__ */ jsx(PaginatorComponent, {
2968
+ offset: currentOffset,
2969
+ limit,
2970
+ total,
2971
+ onChange: handleChangeOffset,
2972
+ }),
2973
+ [
2974
+ paginator,
2975
+ PaginatorComponent,
2976
+ currentOffset,
2977
+ limit,
2978
+ total,
2979
+ handleChangeOffset,
2980
+ ],
2665
2981
  ),
2666
- });
2982
+ ];
2667
2983
  };
2668
- const EditableCellView = ({
2669
- tableId,
2670
- rowId,
2671
- cellId,
2672
- store,
2673
- className,
2674
- showType,
2675
- }) =>
2676
- /* @__PURE__ */ jsx(EditableThing, {
2677
- thing: useCell(tableId, rowId, cellId, store),
2678
- onThingChange: useSetCellCallback(
2679
- tableId,
2680
- rowId,
2681
- cellId,
2682
- (cell) => cell,
2683
- [],
2684
- store,
2685
- ),
2686
- className: className ?? EDITABLE + CELL,
2687
- showType,
2688
- hasSchema: useStoreOrStoreById(store)?.hasTablesSchema,
2689
- });
2690
- const EditableValueView = ({valueId, store, className, showType}) =>
2691
- /* @__PURE__ */ jsx(EditableThing, {
2692
- thing: useValue(valueId, store),
2693
- onThingChange: useSetValueCallback(valueId, (value) => value, [], store),
2694
- className: className ?? EDITABLE + VALUE,
2695
- showType,
2696
- hasSchema: useStoreOrStoreById(store)?.hasValuesSchema,
2697
- });
2698
2984
  const SortedTablePaginator = ({
2699
2985
  onChange,
2700
2986
  total,
@@ -2740,23 +3026,210 @@ const SortedTablePaginator = ({
2740
3026
  ' of ',
2741
3027
  ],
2742
3028
  }),
2743
- total,
2744
- ' ',
2745
- total != 1 ? plural : singular,
3029
+ total,
3030
+ ' ',
3031
+ total != 1 ? plural : singular,
3032
+ ],
3033
+ });
3034
+ };
3035
+
3036
+ const ResultSortedTableInHtmlTable = ({
3037
+ queryId,
3038
+ cellId,
3039
+ descending,
3040
+ offset,
3041
+ limit,
3042
+ queries,
3043
+ sortOnClick,
3044
+ paginator = false,
3045
+ customCells,
3046
+ extraCellsBefore,
3047
+ extraCellsAfter,
3048
+ onChange,
3049
+ ...props
3050
+ }) => {
3051
+ const [sortAndOffset, handleSort, paginatorComponent] =
3052
+ useSortingAndPagination(
3053
+ cellId,
3054
+ descending,
3055
+ sortOnClick,
3056
+ offset,
3057
+ limit,
3058
+ useResultRowCount(queryId, queries),
3059
+ paginator,
3060
+ onChange,
3061
+ );
3062
+ return /* @__PURE__ */ jsx(HtmlTable, {
3063
+ ...props,
3064
+ params: useParams(
3065
+ useCells(
3066
+ useResultTableCellIds(queryId, queries),
3067
+ customCells,
3068
+ ResultCellView,
3069
+ ),
3070
+ useQueriesCellComponentProps(queries, queryId),
3071
+ useResultSortedRowIds(queryId, ...sortAndOffset, limit, queries),
3072
+ extraCellsBefore,
3073
+ extraCellsAfter,
3074
+ sortAndOffset,
3075
+ handleSort,
3076
+ paginatorComponent,
3077
+ ),
3078
+ });
3079
+ };
3080
+
3081
+ const SliceInHtmlTable = ({
3082
+ indexId,
3083
+ sliceId,
3084
+ indexes,
3085
+ editable,
3086
+ customCells,
3087
+ extraCellsBefore,
3088
+ extraCellsAfter,
3089
+ ...props
3090
+ }) => {
3091
+ const [resolvedIndexes, store, tableId] = getIndexStoreTableId(
3092
+ useIndexesOrIndexesById(indexes),
3093
+ indexId,
3094
+ );
3095
+ return /* @__PURE__ */ jsx(HtmlTable, {
3096
+ ...props,
3097
+ params: useParams(
3098
+ useCells(
3099
+ useTableCellIds(tableId, store),
3100
+ customCells,
3101
+ editable ? EditableCellView : CellView,
3102
+ ),
3103
+ useStoreCellComponentProps(store, tableId),
3104
+ useSliceRowIds(indexId, sliceId, resolvedIndexes),
3105
+ extraCellsBefore,
3106
+ extraCellsAfter,
3107
+ ),
3108
+ });
3109
+ };
3110
+
3111
+ const SortedTableInHtmlTable = ({
3112
+ tableId,
3113
+ cellId,
3114
+ descending,
3115
+ offset,
3116
+ limit,
3117
+ store,
3118
+ editable,
3119
+ sortOnClick,
3120
+ paginator = false,
3121
+ onChange,
3122
+ customCells,
3123
+ extraCellsBefore,
3124
+ extraCellsAfter,
3125
+ ...props
3126
+ }) => {
3127
+ const [sortAndOffset, handleSort, paginatorComponent] =
3128
+ useSortingAndPagination(
3129
+ cellId,
3130
+ descending,
3131
+ sortOnClick,
3132
+ offset,
3133
+ limit,
3134
+ useRowCount(tableId, store),
3135
+ paginator,
3136
+ onChange,
3137
+ );
3138
+ return /* @__PURE__ */ jsx(HtmlTable, {
3139
+ ...props,
3140
+ params: useParams(
3141
+ useCells(
3142
+ useTableCellIds(tableId, store),
3143
+ customCells,
3144
+ editable ? EditableCellView : CellView,
3145
+ ),
3146
+ useStoreCellComponentProps(store, tableId),
3147
+ useSortedRowIds(tableId, ...sortAndOffset, limit, store),
3148
+ extraCellsBefore,
3149
+ extraCellsAfter,
3150
+ sortAndOffset,
3151
+ handleSort,
3152
+ paginatorComponent,
3153
+ ),
3154
+ });
3155
+ };
3156
+
3157
+ const extraValueCells = (
3158
+ extraValueCells2 = [],
3159
+ extraValueCellProps,
3160
+ after = 0,
3161
+ ) =>
3162
+ arrayMap(extraValueCells2, ({component: Component}, index) =>
3163
+ /* @__PURE__ */ jsx(
3164
+ 'td',
3165
+ {
3166
+ className: EXTRA,
3167
+ children: /* @__PURE__ */ jsx(Component, {...extraValueCellProps}),
3168
+ },
3169
+ extraKey(index, after),
3170
+ ),
3171
+ );
3172
+ const ValuesInHtmlTable = ({
3173
+ store,
3174
+ editable = false,
3175
+ valueComponent: Value = editable ? EditableValueView : ValueView,
3176
+ getValueComponentProps,
3177
+ extraCellsBefore,
3178
+ extraCellsAfter,
3179
+ className,
3180
+ headerRow,
3181
+ idColumn,
3182
+ }) =>
3183
+ /* @__PURE__ */ jsxs('table', {
3184
+ className,
3185
+ children: [
3186
+ headerRow === false
3187
+ ? null
3188
+ : /* @__PURE__ */ jsx('thead', {
3189
+ children: /* @__PURE__ */ jsxs('tr', {
3190
+ children: [
3191
+ extraHeaders(extraCellsBefore),
3192
+ idColumn === false
3193
+ ? null
3194
+ : /* @__PURE__ */ jsx('th', {children: 'Id'}),
3195
+ /* @__PURE__ */ jsx('th', {children: VALUE}),
3196
+ extraHeaders(extraCellsAfter, 1),
3197
+ ],
3198
+ }),
3199
+ }),
3200
+ /* @__PURE__ */ jsx('tbody', {
3201
+ children: arrayMap(useValueIds(store), (valueId) => {
3202
+ const valueProps = {valueId, store};
3203
+ return /* @__PURE__ */ jsxs(
3204
+ 'tr',
3205
+ {
3206
+ children: [
3207
+ extraValueCells(extraCellsBefore, valueProps),
3208
+ idColumn === false
3209
+ ? null
3210
+ : /* @__PURE__ */ jsx('th', {
3211
+ title: valueId,
3212
+ children: valueId,
3213
+ }),
3214
+ /* @__PURE__ */ jsx('td', {
3215
+ children: /* @__PURE__ */ jsx(Value, {
3216
+ ...getProps(getValueComponentProps, valueId),
3217
+ ...valueProps,
3218
+ }),
3219
+ }),
3220
+ extraValueCells(extraCellsAfter, valueProps, 1),
3221
+ ],
3222
+ },
3223
+ valueId,
3224
+ );
3225
+ }),
3226
+ }),
2746
3227
  ],
2747
3228
  });
2748
- };
2749
3229
 
2750
- const Details = ({
2751
- uniqueId,
2752
- summary,
2753
- editable,
2754
- handleEditable,
2755
- children,
2756
- s,
2757
- }) => {
2758
- const open = !!useCell(STATE_TABLE, uniqueId, OPEN_CELL, s);
2759
- const handleToggle = useSetCellCallback(
3230
+ const Details = ({uniqueId, title, editable, handleEditable, children, s}) => {
3231
+ const open = !!useCell$1(STATE_TABLE, uniqueId, OPEN_CELL, s);
3232
+ const handleToggle = useSetCellCallback$1(
2760
3233
  STATE_TABLE,
2761
3234
  uniqueId,
2762
3235
  OPEN_CELL,
@@ -2770,16 +3243,17 @@ const Details = ({
2770
3243
  children: [
2771
3244
  /* @__PURE__ */ jsxs('summary', {
2772
3245
  children: [
2773
- summary,
3246
+ /* @__PURE__ */ jsx('span', {children: title}),
2774
3247
  handleEditable
2775
3248
  ? /* @__PURE__ */ jsx('img', {
2776
3249
  onClick: handleEditable,
2777
3250
  className: editable ? 'done' : 'edit',
3251
+ title: editable ? 'Done editing' : 'Edit',
2778
3252
  })
2779
3253
  : null,
2780
3254
  ],
2781
3255
  }),
2782
- children,
3256
+ /* @__PURE__ */ jsx('div', {children}),
2783
3257
  ],
2784
3258
  });
2785
3259
  };
@@ -2787,7 +3261,7 @@ const Details = ({
2787
3261
  const IndexView = ({indexes, indexesId, indexId, s}) =>
2788
3262
  /* @__PURE__ */ jsx(Details, {
2789
3263
  uniqueId: getUniqueId('i', indexesId, indexId),
2790
- summary: 'Index: ' + indexId,
3264
+ title: 'Index: ' + indexId,
2791
3265
  s,
2792
3266
  children: arrayMap(useSliceIds(indexId, indexes), (sliceId) =>
2793
3267
  /* @__PURE__ */ jsx(
@@ -2808,7 +3282,7 @@ const SliceView = ({indexes, indexesId, indexId, sliceId, s}) => {
2808
3282
  const [editable, handleEditable] = useEditable(uniqueId, s);
2809
3283
  return /* @__PURE__ */ jsx(Details, {
2810
3284
  uniqueId,
2811
- summary: 'Slice: ' + sliceId,
3285
+ title: 'Slice: ' + sliceId,
2812
3286
  editable,
2813
3287
  handleEditable,
2814
3288
  s,
@@ -2827,7 +3301,7 @@ const IndexesView = ({indexesId, s}) => {
2827
3301
  ? null
2828
3302
  : /* @__PURE__ */ jsx(Details, {
2829
3303
  uniqueId: getUniqueId('i', indexesId),
2830
- summary: 'Indexes: ' + (indexesId ?? DEFAULT),
3304
+ title: 'Indexes: ' + (indexesId ?? DEFAULT),
2831
3305
  s,
2832
3306
  children: arrayIsEmpty(indexIds)
2833
3307
  ? 'No indexes defined'
@@ -2849,7 +3323,7 @@ const IndexesView = ({indexesId, s}) => {
2849
3323
  const MetricRow = ({metrics, metricId}) =>
2850
3324
  /* @__PURE__ */ jsxs('tr', {
2851
3325
  children: [
2852
- /* @__PURE__ */ jsx('th', {children: metricId}),
3326
+ /* @__PURE__ */ jsx('th', {title: metricId, children: metricId}),
2853
3327
  /* @__PURE__ */ jsx('td', {children: metrics?.getTableId(metricId)}),
2854
3328
  /* @__PURE__ */ jsx('td', {children: useMetric(metricId, metrics)}),
2855
3329
  ],
@@ -2861,7 +3335,7 @@ const MetricsView = ({metricsId, s}) => {
2861
3335
  ? null
2862
3336
  : /* @__PURE__ */ jsx(Details, {
2863
3337
  uniqueId: getUniqueId('m', metricsId),
2864
- summary: 'Metrics: ' + (metricsId ?? DEFAULT),
3338
+ title: 'Metrics: ' + (metricsId ?? DEFAULT),
2865
3339
  s,
2866
3340
  children: arrayIsEmpty(metricIds)
2867
3341
  ? 'No metrics defined'
@@ -2891,9 +3365,9 @@ const MetricsView = ({metricsId, s}) => {
2891
3365
  const QueryView = ({queries, queriesId, queryId, s}) => {
2892
3366
  const uniqueId = getUniqueId('q', queriesId, queryId);
2893
3367
  const [cellId, descending, offset] = jsonParse(
2894
- useCell(STATE_TABLE, uniqueId, SORT_CELL, s) ?? '[]',
3368
+ useCell$1(STATE_TABLE, uniqueId, SORT_CELL, s) ?? '[]',
2895
3369
  );
2896
- const handleChange = useSetCellCallback(
3370
+ const handleChange = useSetCellCallback$1(
2897
3371
  STATE_TABLE,
2898
3372
  uniqueId,
2899
3373
  SORT_CELL,
@@ -2903,7 +3377,7 @@ const QueryView = ({queries, queriesId, queryId, s}) => {
2903
3377
  );
2904
3378
  return /* @__PURE__ */ jsx(Details, {
2905
3379
  uniqueId,
2906
- summary: 'Query: ' + queryId,
3380
+ title: 'Query: ' + queryId,
2907
3381
  s,
2908
3382
  children: /* @__PURE__ */ jsx(ResultSortedTableInHtmlTable, {
2909
3383
  queryId,
@@ -2925,7 +3399,7 @@ const QueriesView = ({queriesId, s}) => {
2925
3399
  ? null
2926
3400
  : /* @__PURE__ */ jsx(Details, {
2927
3401
  uniqueId: getUniqueId('q', queriesId),
2928
- summary: 'Queries: ' + (queriesId ?? DEFAULT),
3402
+ title: 'Queries: ' + (queriesId ?? DEFAULT),
2929
3403
  s,
2930
3404
  children: arrayIsEmpty(queryIds)
2931
3405
  ? 'No queries defined'
@@ -2954,7 +3428,7 @@ const RelationshipView = ({
2954
3428
  const [editable, handleEditable] = useEditable(uniqueId, s);
2955
3429
  return /* @__PURE__ */ jsx(Details, {
2956
3430
  uniqueId,
2957
- summary: 'Relationship: ' + relationshipId,
3431
+ title: 'Relationship: ' + relationshipId,
2958
3432
  editable,
2959
3433
  handleEditable,
2960
3434
  s,
@@ -2972,7 +3446,7 @@ const RelationshipsView = ({relationshipsId, s}) => {
2972
3446
  ? null
2973
3447
  : /* @__PURE__ */ jsx(Details, {
2974
3448
  uniqueId: getUniqueId('r', relationshipsId),
2975
- summary: 'Relationships: ' + (relationshipsId ?? DEFAULT),
3449
+ title: 'Relationships: ' + (relationshipsId ?? DEFAULT),
2976
3450
  s,
2977
3451
  children: arrayIsEmpty(relationshipIds)
2978
3452
  ? 'No relationships defined'
@@ -2991,12 +3465,318 @@ const RelationshipsView = ({relationshipsId, s}) => {
2991
3465
  });
2992
3466
  };
2993
3467
 
3468
+ const getNewIdFromSuggestedId = (suggestedId, has) => {
3469
+ let newId;
3470
+ let suffix = 0;
3471
+ while (
3472
+ has(
3473
+ (newId =
3474
+ suggestedId +
3475
+ (suffix > 0 ? ' (copy' + (suffix > 1 ? ' ' + suffix : '') + ')' : '')),
3476
+ )
3477
+ ) {
3478
+ suffix++;
3479
+ }
3480
+ return newId;
3481
+ };
3482
+ const ConfirmableActions = ({actions, ...props}) => {
3483
+ const [confirming, setConfirming] = useState();
3484
+ const handleDone = useCallback(() => setConfirming(null), []);
3485
+ useEffect(() => {
3486
+ if (confirming != null) {
3487
+ const handleKeyDown = (e) => {
3488
+ if (confirming != null && e.key === 'Escape') {
3489
+ e.preventDefault();
3490
+ handleDone();
3491
+ }
3492
+ };
3493
+ document.addEventListener('keydown', handleKeyDown);
3494
+ return () => document.removeEventListener('keydown', handleKeyDown);
3495
+ }
3496
+ }, [confirming, handleDone]);
3497
+ if (confirming != null) {
3498
+ const [, , Component] = actions[confirming];
3499
+ return /* @__PURE__ */ jsxs(Fragment, {
3500
+ children: [
3501
+ /* @__PURE__ */ jsx(Component, {onDone: handleDone, ...props}),
3502
+ /* @__PURE__ */ jsx('img', {
3503
+ onClick: handleDone,
3504
+ title: 'Cancel',
3505
+ className: 'cancel',
3506
+ }),
3507
+ ],
3508
+ });
3509
+ } else {
3510
+ return actions.map(([icon, title], index) =>
3511
+ /* @__PURE__ */ jsx(
3512
+ 'img',
3513
+ {
3514
+ title,
3515
+ className: icon,
3516
+ onClick: () => setConfirming(index),
3517
+ },
3518
+ index,
3519
+ ),
3520
+ );
3521
+ }
3522
+ };
3523
+ const NewId = ({onDone, suggestedId, has, set, prompt = 'New Id'}) => {
3524
+ const [newId, setNewId] = useState(suggestedId);
3525
+ const [newIdOk, setNewIdOk] = useState(true);
3526
+ const [previousSuggestedId, setPreviousSuggestedNewId] =
3527
+ useState(suggestedId);
3528
+ const handleNewIdChange = (e) => {
3529
+ setNewId(e.target.value);
3530
+ setNewIdOk(!has(e.target.value));
3531
+ };
3532
+ const handleClick = useCallback(() => {
3533
+ if (has(newId)) {
3534
+ setNewIdOk(false);
3535
+ } else {
3536
+ set(newId);
3537
+ onDone();
3538
+ }
3539
+ }, [onDone, setNewIdOk, has, set, newId]);
3540
+ const handleKeyDown = useCallback(
3541
+ (e) => {
3542
+ if (e.key === 'Enter') {
3543
+ e.preventDefault();
3544
+ handleClick();
3545
+ }
3546
+ },
3547
+ [handleClick],
3548
+ );
3549
+ if (suggestedId != previousSuggestedId) {
3550
+ setNewId(suggestedId);
3551
+ setPreviousSuggestedNewId(suggestedId);
3552
+ }
3553
+ return /* @__PURE__ */ jsxs(Fragment, {
3554
+ children: [
3555
+ prompt + ': ',
3556
+ /* @__PURE__ */ jsx('input', {
3557
+ type: 'text',
3558
+ value: newId,
3559
+ onChange: handleNewIdChange,
3560
+ onKeyDown: handleKeyDown,
3561
+ autoFocus: true,
3562
+ }),
3563
+ ' ',
3564
+ /* @__PURE__ */ jsx('img', {
3565
+ onClick: handleClick,
3566
+ title: newIdOk ? 'Confirm' : 'Id already exists',
3567
+ className: newIdOk ? 'ok' : 'okDis',
3568
+ }),
3569
+ ],
3570
+ });
3571
+ };
3572
+ const Delete = ({onClick, prompt = 'Delete'}) => {
3573
+ const handleKeyDown = useCallback(
3574
+ (e) => {
3575
+ if (e.key === 'Enter') {
3576
+ e.preventDefault();
3577
+ onClick();
3578
+ }
3579
+ },
3580
+ [onClick],
3581
+ );
3582
+ useEffect(() => {
3583
+ document.addEventListener('keydown', handleKeyDown);
3584
+ return () => document.removeEventListener('keydown', handleKeyDown);
3585
+ }, [handleKeyDown]);
3586
+ return /* @__PURE__ */ jsxs(Fragment, {
3587
+ children: [
3588
+ prompt,
3589
+ '? ',
3590
+ /* @__PURE__ */ jsx('img', {onClick, title: 'Confirm', className: 'ok'}),
3591
+ ],
3592
+ });
3593
+ };
3594
+ const Actions = ({left, right}) =>
3595
+ /* @__PURE__ */ jsxs('div', {
3596
+ className: 'actions',
3597
+ children: [
3598
+ /* @__PURE__ */ jsx('div', {children: left}),
3599
+ /* @__PURE__ */ jsx('div', {children: right}),
3600
+ ],
3601
+ });
3602
+
3603
+ const useHasTableCallback = (storeOrStoreId) => {
3604
+ const store = useStoreOrStoreById(storeOrStoreId);
3605
+ return useCallback((tableId) => store?.hasTable(tableId) ?? false, [store]);
3606
+ };
3607
+ const AddTable = ({onDone, store}) => {
3608
+ const has = useHasTableCallback(store);
3609
+ return /* @__PURE__ */ jsx(NewId, {
3610
+ onDone,
3611
+ suggestedId: getNewIdFromSuggestedId('table', has),
3612
+ has,
3613
+ set: useSetTableCallback(
3614
+ (newId) => newId,
3615
+ () => ({row: {cell: ''}}),
3616
+ [],
3617
+ store,
3618
+ ),
3619
+ prompt: 'Add table',
3620
+ });
3621
+ };
3622
+ const DeleteTables = ({onDone, store}) =>
3623
+ /* @__PURE__ */ jsx(Delete, {
3624
+ onClick: useDelTablesCallback(store, onDone),
3625
+ prompt: 'Delete all tables',
3626
+ });
3627
+ const TablesActions = ({store}) =>
3628
+ /* @__PURE__ */ jsx(Actions, {
3629
+ left: /* @__PURE__ */ jsx(ConfirmableActions, {
3630
+ actions: [['add', 'Add table', AddTable]],
3631
+ store,
3632
+ }),
3633
+ right: useHasTables(store)
3634
+ ? /* @__PURE__ */ jsx(ConfirmableActions, {
3635
+ actions: [['delete', 'Delete all tables', DeleteTables]],
3636
+ store,
3637
+ })
3638
+ : null,
3639
+ });
3640
+ const AddRow = ({onDone, tableId, store}) => {
3641
+ const has = useHasRowCallback(store, tableId);
3642
+ return /* @__PURE__ */ jsx(NewId, {
3643
+ onDone,
3644
+ suggestedId: getNewIdFromSuggestedId('row', has),
3645
+ has,
3646
+ set: useSetRowCallback(
3647
+ tableId,
3648
+ (newId) => newId,
3649
+ (_, store2) =>
3650
+ objNew(
3651
+ arrayMap(store2.getTableCellIds(tableId), (cellId) => [cellId, '']),
3652
+ ),
3653
+ ),
3654
+ prompt: 'Add row',
3655
+ });
3656
+ };
3657
+ const CloneTable = ({onDone, tableId, store: storeOrStoreId}) => {
3658
+ const store = useStoreOrStoreById(storeOrStoreId);
3659
+ const has = useHasTableCallback(store);
3660
+ return /* @__PURE__ */ jsx(NewId, {
3661
+ onDone,
3662
+ suggestedId: getNewIdFromSuggestedId(tableId, has),
3663
+ has,
3664
+ set: useSetTableCallback(
3665
+ (tableId2) => tableId2,
3666
+ (_, store2) => store2.getTable(tableId),
3667
+ ),
3668
+ prompt: 'Clone table to',
3669
+ });
3670
+ };
3671
+ const DeleteTable = ({onDone, tableId, store}) =>
3672
+ /* @__PURE__ */ jsx(Delete, {
3673
+ onClick: useDelTableCallback(tableId, store, onDone),
3674
+ prompt: 'Delete table',
3675
+ });
3676
+ const TableActions1 = ({tableId, store}) =>
3677
+ /* @__PURE__ */ jsx(ConfirmableActions, {
3678
+ actions: [['add', 'Add row', AddRow]],
3679
+ store,
3680
+ tableId,
3681
+ });
3682
+ const TableActions2 = ({tableId, store}) =>
3683
+ /* @__PURE__ */ jsx(ConfirmableActions, {
3684
+ actions: [
3685
+ ['clone', 'Clone table', CloneTable],
3686
+ ['delete', 'Delete table', DeleteTable],
3687
+ ],
3688
+ store,
3689
+ tableId,
3690
+ });
3691
+ const useHasRowCallback = (storeOrStoreId, tableId) => {
3692
+ const store = useStoreOrStoreById(storeOrStoreId);
3693
+ return useCallback(
3694
+ (rowId) => store?.hasRow(tableId, rowId) ?? false,
3695
+ [store, tableId],
3696
+ );
3697
+ };
3698
+ const AddCell = ({onDone, tableId, rowId, store: storeOrStoreId}) => {
3699
+ const store = useStoreOrStoreById(storeOrStoreId);
3700
+ const has = useCallback(
3701
+ (cellId) => store.hasCell(tableId, rowId, cellId),
3702
+ [store, tableId, rowId],
3703
+ );
3704
+ return /* @__PURE__ */ jsx(NewId, {
3705
+ onDone,
3706
+ suggestedId: getNewIdFromSuggestedId('cell', has),
3707
+ has,
3708
+ set: useSetCellCallback(
3709
+ tableId,
3710
+ rowId,
3711
+ (newId) => newId,
3712
+ () => '',
3713
+ [],
3714
+ store,
3715
+ ),
3716
+ prompt: 'Add cell',
3717
+ });
3718
+ };
3719
+ const CloneRow = ({onDone, tableId, rowId, store: storeOrStoreId}) => {
3720
+ const store = useStoreOrStoreById(storeOrStoreId);
3721
+ const has = useHasRowCallback(store, tableId);
3722
+ return /* @__PURE__ */ jsx(NewId, {
3723
+ onDone,
3724
+ suggestedId: getNewIdFromSuggestedId(rowId, has),
3725
+ has,
3726
+ set: useSetRowCallback(
3727
+ tableId,
3728
+ (newId) => newId,
3729
+ (_, store2) => store2.getRow(tableId, rowId),
3730
+ [rowId],
3731
+ ),
3732
+ prompt: 'Clone row to',
3733
+ });
3734
+ };
3735
+ const DeleteRow = ({onDone, tableId, rowId, store}) =>
3736
+ /* @__PURE__ */ jsx(Delete, {
3737
+ onClick: useDelRowCallback(tableId, rowId, store, onDone),
3738
+ prompt: 'Delete row',
3739
+ });
3740
+ const RowActions = ({tableId, rowId, store}) =>
3741
+ /* @__PURE__ */ jsx(ConfirmableActions, {
3742
+ actions: [
3743
+ ['add', 'Add cell', AddCell],
3744
+ ['clone', 'Clone row', CloneRow],
3745
+ ['delete', 'Delete row', DeleteRow],
3746
+ ],
3747
+ store,
3748
+ tableId,
3749
+ rowId,
3750
+ });
3751
+ const CellDelete = ({onDone, tableId, rowId, cellId, store}) =>
3752
+ /* @__PURE__ */ jsx(Delete, {
3753
+ onClick: useDelCellCallback(tableId, rowId, cellId, true, store, onDone),
3754
+ prompt: 'Delete cell',
3755
+ });
3756
+ const CellActions = ({tableId, rowId, cellId, store}) =>
3757
+ /* @__PURE__ */ jsx(ConfirmableActions, {
3758
+ actions: [['delete', 'Delete cell', CellDelete]],
3759
+ store,
3760
+ tableId,
3761
+ rowId,
3762
+ cellId,
3763
+ });
3764
+
3765
+ const rowActions = [{label: '', component: RowActions}];
3766
+ const EditableCellViewWithActions = (props) =>
3767
+ /* @__PURE__ */ jsxs(Fragment, {
3768
+ children: [
3769
+ /* @__PURE__ */ jsx(EditableCellView, {...props}),
3770
+ useHasCell(props.tableId, props.rowId, props.cellId, props.store) &&
3771
+ /* @__PURE__ */ jsx(CellActions, {...props}),
3772
+ ],
3773
+ });
2994
3774
  const TableView = ({tableId, store, storeId, s}) => {
2995
3775
  const uniqueId = getUniqueId('t', storeId, tableId);
2996
3776
  const [cellId, descending, offset] = jsonParse(
2997
- useCell(STATE_TABLE, uniqueId, SORT_CELL, s) ?? '[]',
3777
+ useCell$1(STATE_TABLE, uniqueId, SORT_CELL, s) ?? '[]',
2998
3778
  );
2999
- const handleChange = useSetCellCallback(
3779
+ const handleChange = useSetCellCallback$1(
3000
3780
  STATE_TABLE,
3001
3781
  uniqueId,
3002
3782
  SORT_CELL,
@@ -3005,66 +3785,183 @@ const TableView = ({tableId, store, storeId, s}) => {
3005
3785
  s,
3006
3786
  );
3007
3787
  const [editable, handleEditable] = useEditable(uniqueId, s);
3008
- return /* @__PURE__ */ jsx(Details, {
3788
+ const CellComponent = editable ? EditableCellViewWithActions : CellView;
3789
+ return /* @__PURE__ */ jsxs(Details, {
3009
3790
  uniqueId,
3010
- summary: TABLE + ': ' + tableId,
3791
+ title: TABLE + ': ' + tableId,
3011
3792
  editable,
3012
3793
  handleEditable,
3013
3794
  s,
3014
- children: /* @__PURE__ */ jsx(SortedTableInHtmlTable, {
3015
- tableId,
3795
+ children: [
3796
+ /* @__PURE__ */ jsx(SortedTableInHtmlTable, {
3797
+ tableId,
3798
+ store,
3799
+ cellId,
3800
+ descending,
3801
+ offset,
3802
+ limit: 10,
3803
+ paginator: true,
3804
+ sortOnClick: true,
3805
+ onChange: handleChange,
3806
+ editable,
3807
+ extraCellsAfter: editable ? rowActions : [],
3808
+ customCells: objNew(
3809
+ arrayMap(useTableCellIds$1(tableId, store), (cellId2) => [
3810
+ cellId2,
3811
+ {label: cellId2, component: CellComponent},
3812
+ ]),
3813
+ ),
3814
+ }),
3815
+ editable
3816
+ ? /* @__PURE__ */ jsxs('div', {
3817
+ className: 'actions',
3818
+ children: [
3819
+ /* @__PURE__ */ jsx('div', {
3820
+ children: /* @__PURE__ */ jsx(TableActions1, {tableId, store}),
3821
+ }),
3822
+ /* @__PURE__ */ jsx('div', {
3823
+ children: /* @__PURE__ */ jsx(TableActions2, {tableId, store}),
3824
+ }),
3825
+ ],
3826
+ })
3827
+ : null,
3828
+ ],
3829
+ });
3830
+ };
3831
+ const TablesView = ({store, storeId, s}) => {
3832
+ const uniqueId = getUniqueId('ts', storeId);
3833
+ const [editable, handleEditable] = useEditable(uniqueId, s);
3834
+ const tableIds = useTableIds(store);
3835
+ return /* @__PURE__ */ jsxs(Details, {
3836
+ uniqueId,
3837
+ title: TABLES,
3838
+ editable,
3839
+ handleEditable,
3840
+ s,
3841
+ children: [
3842
+ arrayIsEmpty(tableIds)
3843
+ ? /* @__PURE__ */ jsx('caption', {children: 'No tables.'})
3844
+ : sortedIdsMap(tableIds, (tableId) =>
3845
+ /* @__PURE__ */ jsx(
3846
+ TableView,
3847
+ {
3848
+ store,
3849
+ storeId,
3850
+ tableId,
3851
+ s,
3852
+ },
3853
+ tableId,
3854
+ ),
3855
+ ),
3856
+ editable ? /* @__PURE__ */ jsx(TablesActions, {store}) : null,
3857
+ ],
3858
+ });
3859
+ };
3860
+
3861
+ const useHasValueCallback = (storeOrStoreId) => {
3862
+ const store = useStoreOrStoreById(storeOrStoreId);
3863
+ return useCallback((valueId) => store?.hasValue(valueId) ?? false, [store]);
3864
+ };
3865
+ const AddValue = ({onDone, store}) => {
3866
+ const has = useHasValueCallback(store);
3867
+ return /* @__PURE__ */ jsx(NewId, {
3868
+ onDone,
3869
+ suggestedId: getNewIdFromSuggestedId('value', has),
3870
+ has,
3871
+ set: useSetValueCallback(
3872
+ (newId) => newId,
3873
+ () => '',
3874
+ [],
3875
+ store,
3876
+ ),
3877
+ prompt: 'Add value',
3878
+ });
3879
+ };
3880
+ const DeleteValues = ({onDone, store}) =>
3881
+ /* @__PURE__ */ jsx(Delete, {
3882
+ onClick: useDelValuesCallback(store, onDone),
3883
+ prompt: 'Delete all values',
3884
+ });
3885
+ const ValuesActions = ({store}) =>
3886
+ /* @__PURE__ */ jsx(Actions, {
3887
+ left: /* @__PURE__ */ jsx(ConfirmableActions, {
3888
+ actions: [['add', 'Add value', AddValue]],
3016
3889
  store,
3017
- cellId,
3018
- descending,
3019
- offset,
3020
- limit: 10,
3021
- paginator: true,
3022
- sortOnClick: true,
3023
- onChange: handleChange,
3024
- editable,
3025
3890
  }),
3891
+ right: useHasValues(store)
3892
+ ? /* @__PURE__ */ jsx(ConfirmableActions, {
3893
+ actions: [['delete', 'Delete all values', DeleteValues]],
3894
+ store,
3895
+ })
3896
+ : null,
3897
+ });
3898
+ const CloneValue = ({onDone, valueId, store}) => {
3899
+ const has = useHasValueCallback(store);
3900
+ return /* @__PURE__ */ jsx(NewId, {
3901
+ onDone,
3902
+ suggestedId: getNewIdFromSuggestedId(valueId, has),
3903
+ has,
3904
+ set: useSetValueCallback(
3905
+ (newId) => newId,
3906
+ (_, store2) => store2.getValue(valueId) ?? '',
3907
+ [valueId],
3908
+ store,
3909
+ ),
3910
+ prompt: 'Clone value to',
3026
3911
  });
3027
3912
  };
3913
+ const DeleteValue = ({onDone, valueId, store}) =>
3914
+ /* @__PURE__ */ jsx(Delete, {
3915
+ onClick: useDelValueCallback(valueId, store, onDone),
3916
+ prompt: 'Delete value',
3917
+ });
3918
+ const ValueActions = ({valueId, store}) =>
3919
+ /* @__PURE__ */ jsx(ConfirmableActions, {
3920
+ actions: [
3921
+ ['clone', 'Clone value', CloneValue],
3922
+ ['delete', 'Delete value', DeleteValue],
3923
+ ],
3924
+ store,
3925
+ valueId,
3926
+ });
3927
+
3928
+ const valueActions = [{label: '', component: ValueActions}];
3028
3929
  const ValuesView = ({store, storeId, s}) => {
3029
3930
  const uniqueId = getUniqueId('v', storeId);
3030
3931
  const [editable, handleEditable] = useEditable(uniqueId, s);
3031
- return arrayIsEmpty(useValueIds(store))
3032
- ? null
3033
- : /* @__PURE__ */ jsx(Details, {
3034
- uniqueId,
3035
- summary: VALUES,
3036
- editable,
3037
- handleEditable,
3038
- s,
3039
- children: /* @__PURE__ */ jsx(ValuesInHtmlTable, {store, editable}),
3040
- });
3932
+ return /* @__PURE__ */ jsxs(Details, {
3933
+ uniqueId,
3934
+ title: VALUES,
3935
+ editable,
3936
+ handleEditable,
3937
+ s,
3938
+ children: [
3939
+ arrayIsEmpty(useValueIds$1(store))
3940
+ ? /* @__PURE__ */ jsx('caption', {children: 'No values.'})
3941
+ : /* @__PURE__ */ jsx(ValuesInHtmlTable, {
3942
+ store,
3943
+ editable,
3944
+ extraCellsAfter: editable ? valueActions : [],
3945
+ }),
3946
+ editable ? /* @__PURE__ */ jsx(ValuesActions, {store}) : null,
3947
+ ],
3948
+ });
3041
3949
  };
3950
+
3042
3951
  const StoreView = ({storeId, s}) => {
3043
3952
  const store = useStore(storeId);
3044
- const tableIds = useTableIds(store);
3045
3953
  return isUndefined(store)
3046
3954
  ? null
3047
3955
  : /* @__PURE__ */ jsxs(Details, {
3048
3956
  uniqueId: getUniqueId('s', storeId),
3049
- summary:
3957
+ title:
3050
3958
  (store.isMergeable() ? 'Mergeable' : '') +
3051
3959
  'Store: ' +
3052
3960
  (storeId ?? DEFAULT),
3053
3961
  s,
3054
3962
  children: [
3055
3963
  /* @__PURE__ */ jsx(ValuesView, {storeId, store, s}),
3056
- sortedIdsMap(tableIds, (tableId) =>
3057
- /* @__PURE__ */ jsx(
3058
- TableView,
3059
- {
3060
- store,
3061
- storeId,
3062
- tableId,
3063
- s,
3064
- },
3065
- tableId,
3066
- ),
3067
- ),
3964
+ /* @__PURE__ */ jsx(TablesView, {storeId, store, s}),
3068
3965
  ],
3069
3966
  });
3070
3967
  };
@@ -3184,9 +4081,10 @@ class ErrorBoundary extends PureComponent {
3184
4081
  }
3185
4082
 
3186
4083
  const Header = ({s}) => {
3187
- const position = useValue(POSITION_VALUE, s) ?? 1;
3188
- const handleClose = useSetValueCallback(OPEN_VALUE, () => false, [], s);
3189
- const handleDock = useSetValueCallback(
4084
+ const position = useValue$1(POSITION_VALUE, s) ?? 1;
4085
+ const handleClick = () => open('https://tinybase.org', '_blank');
4086
+ const handleClose = useSetValueCallback$1(OPEN_VALUE, () => false, [], s);
4087
+ const handleDock = useSetValueCallback$1(
3190
4088
  POSITION_VALUE,
3191
4089
  (event) => Number(event[CURRENT_TARGET].dataset.id),
3192
4090
  [],
@@ -3194,7 +4092,11 @@ const Header = ({s}) => {
3194
4092
  );
3195
4093
  return /* @__PURE__ */ jsxs('header', {
3196
4094
  children: [
3197
- /* @__PURE__ */ jsx('img', {title: TITLE}),
4095
+ /* @__PURE__ */ jsx('img', {
4096
+ className: 'flat',
4097
+ title: TITLE,
4098
+ onClick: handleClick,
4099
+ }),
3198
4100
  /* @__PURE__ */ jsx('span', {children: TITLE}),
3199
4101
  arrayMap(POSITIONS, (name, p) =>
3200
4102
  p == position
@@ -3209,14 +4111,18 @@ const Header = ({s}) => {
3209
4111
  p,
3210
4112
  ),
3211
4113
  ),
3212
- /* @__PURE__ */ jsx('img', {onClick: handleClose, title: 'Close'}),
4114
+ /* @__PURE__ */ jsx('img', {
4115
+ className: 'flat',
4116
+ onClick: handleClose,
4117
+ title: 'Close',
4118
+ }),
3213
4119
  ],
3214
4120
  });
3215
4121
  };
3216
4122
 
3217
4123
  const Panel = ({s}) => {
3218
- const position = useValue(POSITION_VALUE, s) ?? 1;
3219
- return useValue(OPEN_VALUE, s)
4124
+ const position = useValue$1(POSITION_VALUE, s) ?? 1;
4125
+ return useValue$1(OPEN_VALUE, s)
3220
4126
  ? /* @__PURE__ */ jsxs('main', {
3221
4127
  'data-position': position,
3222
4128
  children: [
@@ -3232,70 +4138,237 @@ const Panel = ({s}) => {
3232
4138
  var img =
3233
4139
  "data:image/svg+xml,%3csvg viewBox='0 0 680 680' xmlns='http://www.w3.org/2000/svg' style='width:680px%3bheight:680px'%3e %3cpath stroke='white' stroke-width='80' fill='none' d='M340 617a84 241 90 11.01 0zM131 475a94 254 70 10428-124 114 286 70 01-428 124zm0-140a94 254 70 10428-124 114 286 70 01-428 124zm-12-127a94 254 70 00306 38 90 260 90 01-306-38zm221 3a74 241 90 11.01 0z' /%3e %3cpath fill='%23d81b60' d='M131 475a94 254 70 10428-124 114 286 70 01-428 124zm0-140a94 254 70 10428-124 114 286 70 01-428 124z' /%3e %3cpath d='M249 619a94 240 90 00308-128 114 289 70 01-308 128zM119 208a94 254 70 00306 38 90 260 90 01-306-38zm221 3a74 241 90 11.01 0z' /%3e%3c/svg%3e";
3234
4140
 
3235
- const PENCIL = 'M20 80l5-15l40-40l10 10l-40 40l-15 5m5-15l10 10';
3236
- const PRE_CSS = 'content:url("';
4141
+ const PRE_CSS = 'url("';
3237
4142
  const POST_CSS = '")';
3238
- const PRE =
3239
- PRE_CSS +
3240
- `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' stroke-width='4' stroke='white' fill='none'>`;
3241
- const POST = `</svg>` + POST_CSS;
3242
- const LOGO_SVG = PRE_CSS + img + POST_CSS;
4143
+ const getCssSvg = (path, color = 'white') => ({
4144
+ content:
4145
+ PRE_CSS +
4146
+ `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960' fill='${color}'><path d='${path}' /></svg>` +
4147
+ POST_CSS,
4148
+ });
4149
+ const VERTICAL_THIN = 'v560h120v-560h-120Z';
4150
+ const VERTICAL_THICK = 'v560h360v-560h-360Z';
4151
+ const HORIZONTAL_THIN = 'v120h560v-120h-560Z';
4152
+ const HORIZONTAL_THICK = 'v360h560v-360h-560Z';
4153
+ const LOGO_SVG = {content: PRE_CSS + img + POST_CSS};
3243
4154
  const POSITIONS_SVG = arrayMap(
3244
4155
  [
3245
- [20, 20, 20, 60],
3246
- [20, 20, 60, 20],
3247
- [20, 60, 60, 20],
3248
- [60, 20, 20, 60],
3249
- [30, 30, 40, 40],
4156
+ `M200-760${VERTICAL_THIN} M400-760${VERTICAL_THICK}`,
4157
+ `M200-760${HORIZONTAL_THIN} M200-560${HORIZONTAL_THICK}`,
4158
+ `M200-760${HORIZONTAL_THICK} M200-320${HORIZONTAL_THIN}`,
4159
+ `M200-760${VERTICAL_THICK} M640-760${VERTICAL_THIN}`,
3250
4160
  ],
3251
- ([x, y, w, h]) =>
3252
- PRE +
3253
- `<rect x='20' y='20' width='60' height='60' fill='grey'/><rect x='${x}' y='${y}' width='${w}' height='${h}' fill='white'/>` +
3254
- POST,
4161
+ (path) =>
4162
+ getCssSvg(
4163
+ 'M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Z' +
4164
+ path,
4165
+ ),
4166
+ );
4167
+ arrayPush(
4168
+ POSITIONS_SVG,
4169
+ getCssSvg(
4170
+ 'M120-120v-200h80v120h120v80H120Zm520 0v-80h120v-120h80v200H640ZM120-640v-200h200v80H200v120h-80Zm640 0v-120H640v-80h200v200h-80Z',
4171
+ ),
4172
+ );
4173
+ const CLOSE_SVG = getCssSvg(
4174
+ 'm336-280-56-56 144-144-144-143 56-56 144 144 143-144 56 56-144 143 144 144-56 56-143-144-144 144Z',
4175
+ );
4176
+ const EDIT_SVG = getCssSvg(
4177
+ 'M200-200h57l391-391-57-57-391 391v57Zm-80 80v-170l528-527q12-11 26.5-17t30.5-6q16 0 31 6t26 18l55 56q12 11 17.5 26t5.5 30q0 16-5.5 30.5T817-647L290-120H120Zm640-584-56-56 56 56Zm-141 85-28-29 57 57-29-28Z',
4178
+ );
4179
+ const DONE_SVG = getCssSvg(
4180
+ 'm622-453-56-56 82-82-57-57-82 82-56-56 195-195q12-12 26.5-17.5T705-840q16 0 31 6t26 18l55 56q12 11 17.5 26t5.5 30q0 16-5.5 30.5T817-647L622-453ZM200-200h57l195-195-28-29-29-28-195 195v57ZM792-56 509-338 290-120H120v-169l219-219L56-792l57-57 736 736-57 57Zm-32-648-56-56 56 56Zm-169 56 57 57-57-57ZM424-424l-29-28 57 57-28-29Z',
4181
+ );
4182
+ const ADD_SVG = getCssSvg(
4183
+ 'M440-280h80v-160h160v-80H520v-160h-80v160H280v80h160v160ZM200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm0-560v560-560Z',
4184
+ );
4185
+ const CLONE_SVG = getCssSvg(
4186
+ 'M520-400h80v-120h120v-80H600v-120h-80v120H400v80h120v120ZM320-240q-33 0-56.5-23.5T240-320v-480q0-33 23.5-56.5T320-880h480q33 0 56.5 23.5T880-800v480q0 33-23.5 56.5T800-240H320Zm0-80h480v-480H320v480ZM160-80q-33 0-56.5-23.5T80-160v-560h80v560h560v80H160Zm160-720v480-480Z',
4187
+ );
4188
+ const DELETE_SVG = getCssSvg(
4189
+ 'M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z',
4190
+ );
4191
+ const OK_SVG = getCssSvg(
4192
+ 'm424-296 282-282-56-56-226 226-114-114-56 56 170 170Zm56 216q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z',
4193
+ 'rgb(127,255,127)',
4194
+ );
4195
+ const OK_SVG_DISABLED = getCssSvg(
4196
+ 'm40-120 440-760 440 760H40Zm138-80h604L480-720 178-200Zm302-40q17 0 28.5-11.5T520-280q0-17-11.5-28.5T480-320q-17 0-28.5 11.5T440-280q0 17 11.5 28.5T480-240Zm-40-120h80v-200h-80v200Zm40-100Z',
4197
+ 'rgb(255,255,127)',
4198
+ );
4199
+ const CANCEL_SVG = getCssSvg(
4200
+ 'm336-280 144-144 144 144 56-56-144-144 144-144-56-56-144 144-144-144-56 56 144 144-144 144 56 56ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z',
4201
+ 'rgb(255,127,127)',
4202
+ );
4203
+ const DOWN_SVG = getCssSvg(
4204
+ 'M480-344 240-584l56-56 184 184 184-184 56 56-240 240Z',
4205
+ );
4206
+ const RIGHT_SVG = getCssSvg(
4207
+ 'M504-480 320-664l56-56 240 240-240 240-56-56 184-184Z',
3255
4208
  );
3256
- const CLOSE_SVG = PRE + `<path d='M20 20l60 60M20 80l60-60' />` + POST;
3257
- const EDIT_SVG = PRE + `<path d='${PENCIL}' />` + POST;
3258
- const DONE_SVG = PRE + `<path d='${PENCIL}M20 20l60 60' />` + POST;
3259
4209
 
3260
4210
  const SCROLLBAR = '*::-webkit-scrollbar';
4211
+ const BACKGROUND = 'background';
4212
+ const WIDTH = 'width';
4213
+ const MAX_WIDTH = 'max-' + WIDTH;
4214
+ const MIN_WIDTH = 'min-' + WIDTH;
4215
+ const HEIGHT = 'height';
4216
+ const BORDER = 'border';
4217
+ const BORDER_RADIUS = BORDER + '-radius';
4218
+ const PADDING = 'padding';
4219
+ const MARGIN = 'margin';
4220
+ const MARGIN_RIGHT = MARGIN + '-right';
4221
+ const TOP = 'top';
4222
+ const BOTTOM = 'bottom';
4223
+ const LEFT = 'left';
4224
+ const RIGHT = 'right';
4225
+ const COLOR = 'color';
4226
+ const POSITION = 'position';
4227
+ const BOX_SHADOW = 'box-shadow';
4228
+ const FONT_SIZE = 'font-size';
4229
+ const DISPLAY = 'display';
4230
+ const OVERFLOW = 'overflow';
4231
+ const CURSOR = 'cursor';
4232
+ const VERTICAL_ALIGN = 'vertical-align';
4233
+ const TEXT_ALIGN = 'text-align';
4234
+ const JUSTIFY_CONTENT = 'justify-content';
4235
+ const FIXED = 'fixed';
4236
+ const REVERT = 'revert';
4237
+ const UNSET = 'unset';
4238
+ const NONE = 'none';
4239
+ const FLEX = 'flex';
4240
+ const POINTER = 'pointer';
4241
+ const AUTO = 'auto';
4242
+ const HIDDEN = 'hidden';
4243
+ const NOWRAP = 'nowrap';
4244
+ const oklch = (lPercent, remainder = '% 0.01 ' + cssVar('hue')) =>
4245
+ `oklch(${lPercent}${remainder})`;
4246
+ const cssVar = (name) => `var(--${name})`;
4247
+ const rem = (...rems) => `${rems.join('rem ')}rem`;
4248
+ const px = (...pxs) => `${pxs.join('px ')}px`;
4249
+ const vw = (vw2 = 100) => `${vw2}vw`;
4250
+ const vh = (vh2 = 100) => `${vh2}vh`;
3261
4251
  const APP_STYLESHEET = arrayJoin(
3262
4252
  objToArray(
3263
4253
  {
3264
- '': 'all:initial;font-family:sans-serif;font-size:0.75rem;position:fixed;z-index:999999',
3265
- '*': 'all:revert',
3266
- '*::before': 'all:revert',
3267
- '*::after': 'all:revert',
3268
- [SCROLLBAR]: 'width:0.5rem;height:0.5rem;',
3269
- [SCROLLBAR + '-track']: 'background:#111',
3270
- [SCROLLBAR + '-thumb']: 'background:#999;border:1px solid #111',
3271
- [SCROLLBAR + '-thumb:hover']: 'background:#fff',
3272
- [SCROLLBAR + '-corner']: 'background:#111',
3273
- img: 'width:1rem;height:1rem;background:#111;border:0;vertical-align:text-bottom',
4254
+ '': {
4255
+ all: 'initial',
4256
+ [FONT_SIZE]: rem(0.75),
4257
+ [POSITION]: FIXED,
4258
+ 'font-family': 'inter,sans-serif',
4259
+ 'z-index': 999999,
4260
+ '--bg': oklch(20),
4261
+ '--bg2': oklch(15),
4262
+ '--bg3': oklch(25),
4263
+ '--bg4': oklch(30),
4264
+ '--fg': oklch(85),
4265
+ '--fg2': oklch(60),
4266
+ ['--' + BORDER]: px(1) + ' solid ' + cssVar('bg4'),
4267
+ ['--' + BOX_SHADOW]: px(0, 1, 2, 0) + ' #0007',
4268
+ },
4269
+ '*': {all: REVERT},
4270
+ '*::before': {all: REVERT},
4271
+ '*::after': {all: REVERT},
4272
+ [SCROLLBAR]: {[WIDTH]: rem(0.5), [HEIGHT]: rem(0.5)},
4273
+ [SCROLLBAR + '-thumb']: {[BACKGROUND]: cssVar('bg4')},
4274
+ [SCROLLBAR + '-thumb:hover']: {[BACKGROUND]: cssVar('bg4')},
4275
+ [SCROLLBAR + '-corner']: {[BACKGROUND]: NONE},
4276
+ [SCROLLBAR + '-track']: {[BACKGROUND]: NONE},
4277
+ img: {
4278
+ [WIDTH]: rem(0.8),
4279
+ [HEIGHT]: rem(0.8),
4280
+ [VERTICAL_ALIGN]: 'text-' + BOTTOM,
4281
+ [CURSOR]: POINTER,
4282
+ [MARGIN]: px(-2.5, 2, -2.5, 0),
4283
+ [PADDING]: px(2),
4284
+ [BORDER]: cssVar(BORDER),
4285
+ [BACKGROUND]: cssVar('bg3'),
4286
+ [BOX_SHADOW]: cssVar(BOX_SHADOW),
4287
+ [BORDER_RADIUS]: rem(0.25),
4288
+ },
4289
+ 'img.flat': {[BORDER]: NONE, [BACKGROUND]: NONE, [BOX_SHADOW]: NONE},
3274
4290
  // Nub
3275
- '>img': 'padding:0.25rem;bottom:0;right:0;position:fixed;' + LOGO_SVG,
4291
+ '>img': {
4292
+ [PADDING]: rem(0.25),
4293
+ [BOTTOM]: 0,
4294
+ [RIGHT]: 0,
4295
+ [POSITION]: FIXED,
4296
+ [HEIGHT]: UNSET,
4297
+ [MARGIN]: 0,
4298
+ ...LOGO_SVG,
4299
+ },
3276
4300
  ...objNew(
3277
- arrayMap(['bottom:0;left:0', 'top:0;right:0'], (css, p) => [
3278
- `>img[data-position='${p}']`,
3279
- css,
3280
- ]),
4301
+ arrayMap(
4302
+ [
4303
+ {[BOTTOM]: 0, [LEFT]: 0},
4304
+ {[TOP]: 0, [RIGHT]: 0},
4305
+ ],
4306
+ (css, p) => [`>img[data-position='${p}']`, css],
4307
+ ),
3281
4308
  ),
3282
4309
  // Panel
3283
- main: 'display:flex;flex-direction:column;background:#111d;color:#fff;position:fixed;',
4310
+ main: {
4311
+ [DISPLAY]: FLEX,
4312
+ [COLOR]: cssVar('fg'),
4313
+ [BACKGROUND]: cssVar('bg'),
4314
+ [OVERFLOW]: HIDDEN,
4315
+ [POSITION]: FIXED,
4316
+ [BOX_SHADOW]: cssVar(BOX_SHADOW),
4317
+ 'flex-direction': 'column',
4318
+ },
3284
4319
  ...objNew(
3285
4320
  arrayMap(
3286
4321
  [
3287
- 'bottom:0;left:0;width:35vw;height:100vh',
3288
- 'top:0;right:0;width:100vw;height:30vh',
3289
- 'bottom:0;left:0;width:100vw;height:30vh',
3290
- 'top:0;right:0;width:35vw;height:100vh',
3291
- 'top:0;right:0;width:100vw;height:100vh',
4322
+ {
4323
+ [BOTTOM]: 0,
4324
+ [LEFT]: 0,
4325
+ [WIDTH]: vw(35),
4326
+ [HEIGHT]: vh(),
4327
+ [BORDER + '-' + RIGHT]: cssVar(BORDER),
4328
+ },
4329
+ {
4330
+ [TOP]: 0,
4331
+ [RIGHT]: 0,
4332
+ [WIDTH]: vw(),
4333
+ [HEIGHT]: vh(30),
4334
+ [BORDER + '-' + BOTTOM]: cssVar(BORDER),
4335
+ },
4336
+ {
4337
+ [BOTTOM]: 0,
4338
+ [LEFT]: 0,
4339
+ [WIDTH]: vw(),
4340
+ [HEIGHT]: vh(30),
4341
+ [BORDER + '-' + TOP]: cssVar(BORDER),
4342
+ },
4343
+ {
4344
+ [TOP]: 0,
4345
+ [RIGHT]: 0,
4346
+ [WIDTH]: vw(35),
4347
+ [HEIGHT]: vh(),
4348
+ [BORDER + '-' + LEFT]: cssVar(BORDER),
4349
+ },
4350
+ {[TOP]: 0, [RIGHT]: 0, [WIDTH]: vw(), [HEIGHT]: vh()},
3292
4351
  ],
3293
4352
  (css, p) => [`main[data-position='${p}']`, css],
3294
4353
  ),
3295
4354
  ),
3296
4355
  // Header
3297
- header: 'display:flex;padding:0.25rem;background:#000;align-items:center',
3298
- 'header>img:nth-of-type(1)': LOGO_SVG,
4356
+ header: {
4357
+ [DISPLAY]: FLEX,
4358
+ [PADDING]: rem(0.5),
4359
+ [BOX_SHADOW]: cssVar(BOX_SHADOW),
4360
+ [BACKGROUND]: oklch(30, '% 0.008 var(--hue) / .5'),
4361
+ [WIDTH]: 'calc(100% - .5rem)',
4362
+ [POSITION]: 'absolute',
4363
+ [BORDER + '-' + BOTTOM]: cssVar(BORDER),
4364
+ 'align-items': 'center',
4365
+ 'backdrop-filter': 'blur(4px)',
4366
+ },
4367
+ 'header>img:nth-of-type(1)': {
4368
+ [HEIGHT]: rem(1),
4369
+ [WIDTH]: rem(1),
4370
+ ...LOGO_SVG,
4371
+ },
3299
4372
  'header>img:nth-of-type(6)': CLOSE_SVG,
3300
4373
  ...objNew(
3301
4374
  arrayMap(POSITIONS_SVG, (SVG, p) => [
@@ -3303,42 +4376,140 @@ const APP_STYLESHEET = arrayJoin(
3303
4376
  SVG,
3304
4377
  ]),
3305
4378
  ),
3306
- 'header>span':
3307
- 'flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-left:0.25rem',
4379
+ 'header>span': {
4380
+ [OVERFLOW]: HIDDEN,
4381
+ [FLEX]: 1,
4382
+ 'font-weight': 800,
4383
+ 'white-space': NOWRAP,
4384
+ 'text-overflow': 'ellipsis',
4385
+ },
3308
4386
  // Body
3309
- article: 'padding:0.25rem 0.25rem 0.25rem 0.5rem;overflow:auto;flex:1',
3310
- details: 'margin-left:0.75rem;width:fit-content;',
3311
- 'details img': 'display:none',
3312
- 'details[open]>summary img':
3313
- 'display:unset;background:none;margin-left:0.25rem',
3314
- 'details[open]>summary img.edit': EDIT_SVG,
3315
- 'details[open]>summary img.done': DONE_SVG,
3316
- summary:
3317
- 'margin-left:-0.75rem;line-height:1.25rem;user-select:none;width:fit-content',
4387
+ article: {[OVERFLOW]: AUTO, [FLEX]: 1, [PADDING + '-' + TOP]: rem(2)},
4388
+ details: {
4389
+ [MARGIN]: rem(0.5),
4390
+ [BORDER]: cssVar(BORDER),
4391
+ [BORDER_RADIUS]: rem(0.25),
4392
+ },
4393
+ summary: {
4394
+ [BACKGROUND]: cssVar('bg3'),
4395
+ [MARGIN]: px(-1),
4396
+ [BORDER]: cssVar(BORDER),
4397
+ [PADDING]: rem(0.25, 0.125),
4398
+ [DISPLAY]: FLEX,
4399
+ [BORDER_RADIUS]: rem(0.25),
4400
+ 'user-select': NONE,
4401
+ [JUSTIFY_CONTENT]: 'space-between',
4402
+ 'align-items': 'center',
4403
+ },
4404
+ 'summary>span::before': {
4405
+ [DISPLAY]: 'inline-block',
4406
+ [VERTICAL_ALIGN]: 'sub',
4407
+ [MARGIN]: px(2),
4408
+ [WIDTH]: rem(1),
4409
+ [HEIGHT]: rem(1),
4410
+ ...RIGHT_SVG,
4411
+ },
4412
+ 'details[open]>summary': {
4413
+ 'border-bottom-left-radius': 0,
4414
+ 'border-bottom-right-radius': 0,
4415
+ [MARGIN + '-' + BOTTOM]: 0,
4416
+ },
4417
+ 'details[open]>summary>span::before': DOWN_SVG,
4418
+ 'details>summary img': {[DISPLAY]: NONE},
4419
+ 'details[open]>summary img': {
4420
+ [DISPLAY]: UNSET,
4421
+ [MARGIN + '-' + LEFT]: rem(0.25),
4422
+ },
4423
+ 'details>div': {[OVERFLOW]: AUTO},
4424
+ caption: {
4425
+ [COLOR]: cssVar('fg2'),
4426
+ [PADDING]: rem(0.25, 0.5),
4427
+ [TEXT_ALIGN]: LEFT,
4428
+ 'white-space': NOWRAP,
4429
+ },
4430
+ 'caption button': {
4431
+ [WIDTH]: rem(1.5),
4432
+ [BORDER]: NONE,
4433
+ [BACKGROUND]: NONE,
4434
+ [COLOR]: cssVar('fg'),
4435
+ [PADDING]: 0,
4436
+ [CURSOR]: POINTER,
4437
+ },
4438
+ 'caption button[disabled]': {[COLOR]: cssVar('fg2')},
4439
+ '.actions': {
4440
+ [PADDING]: rem(0.75, 0.5),
4441
+ [MARGIN]: 0,
4442
+ [DISPLAY]: FLEX,
4443
+ [BORDER + '-' + TOP]: cssVar(BORDER),
4444
+ [JUSTIFY_CONTENT]: 'space-between',
4445
+ },
3318
4446
  // tables
3319
- table: 'border-collapse:collapse;table-layout:fixed;margin-bottom:0.5rem',
3320
- 'table input':
3321
- 'background:#111;color:unset;padding:0 0.25rem;border:0;font-size:unset;vertical-align:top;margin:0',
3322
- 'table input[type="number"]': 'width:4rem',
3323
- 'table tbody button':
3324
- 'font-size:0;background:#fff;border-radius:50%;margin:0 0.125rem 0 0;width:0.85rem;color:#111',
3325
- 'table button:first-letter': 'font-size:0.75rem',
3326
- thead: 'background:#222',
3327
- 'th:nth-of-type(1)': 'min-width:2rem;',
3328
- 'th.sorted': 'background:#000',
3329
- 'table caption': 'text-align:left;white-space:nowrap;line-height:1.25rem',
3330
- button: 'width:1.5rem;border:none;background:none;color:#fff;padding:0',
3331
- 'button[disabled]': 'color:#777',
3332
- 'button.next': 'margin-right:0.5rem',
3333
- [`th,#${UNIQUE_ID} td`]:
3334
- 'overflow:hidden;text-overflow:ellipsis;padding:0.25rem 0.5rem;max-width:12rem;white-space:nowrap;border-width:1px 0;border-style:solid;border-color:#777;text-align:left',
3335
- 'span.warn': 'margin:0.25rem;color:#d81b60',
4447
+ table: {
4448
+ [MIN_WIDTH]: '100%',
4449
+ 'border-collapse': 'collapse',
4450
+ 'table-layout': FIXED,
4451
+ },
4452
+ thead: {[BACKGROUND]: cssVar('bg')},
4453
+ [`th,#${UNIQUE_ID} td`]: {
4454
+ [OVERFLOW]: HIDDEN,
4455
+ [PADDING]: rem(0.25, 0.5),
4456
+ [MAX_WIDTH]: rem(20),
4457
+ [BORDER]: cssVar(BORDER),
4458
+ 'text-overflow': 'ellipsis',
4459
+ 'white-space': NOWRAP,
4460
+ 'border-width': px(1, 0, 0),
4461
+ [TEXT_ALIGN]: LEFT,
4462
+ },
4463
+ 'th:first-child': {
4464
+ [WIDTH]: rem(3),
4465
+ [MIN_WIDTH]: rem(3),
4466
+ [MAX_WIDTH]: rem(3),
4467
+ },
4468
+ 'th.sorted': {[BACKGROUND]: cssVar('bg3')},
4469
+ 'td.extra': {[TEXT_ALIGN]: RIGHT},
4470
+ 'tbody button': {
4471
+ [BACKGROUND]: NONE,
4472
+ [BORDER]: NONE,
4473
+ [FONT_SIZE]: 0,
4474
+ [WIDTH]: rem(0.8),
4475
+ [HEIGHT]: rem(0.8),
4476
+ [COLOR]: cssVar('fg2'),
4477
+ [MARGIN]: rem(0, 0.25, 0, -0.25),
4478
+ 'line-height': rem(0.8),
4479
+ },
4480
+ 'tbody button:first-letter': {[FONT_SIZE]: rem(0.8)},
4481
+ input: {
4482
+ [BACKGROUND]: cssVar('bg2'),
4483
+ [COLOR]: UNSET,
4484
+ [PADDING]: px(4),
4485
+ [BORDER]: 0,
4486
+ [MARGIN]: px(-4, 0),
4487
+ [FONT_SIZE]: UNSET,
4488
+ [MAX_WIDTH]: rem(6),
4489
+ },
4490
+ 'input:focus': {'outline-width': 0},
4491
+ 'input[type="number"]': {[WIDTH]: rem(3)},
4492
+ 'input[type="checkbox"]': {[VERTICAL_ALIGN]: px(-2)},
4493
+ '.editableCell': {[DISPLAY]: 'inline-block', [MARGIN_RIGHT]: px(2)},
4494
+ 'button.next': {[MARGIN_RIGHT]: rem(0.5)},
4495
+ 'img.edit': EDIT_SVG,
4496
+ 'img.done': DONE_SVG,
4497
+ 'img.add': ADD_SVG,
4498
+ 'img.clone': CLONE_SVG,
4499
+ 'img.delete': DELETE_SVG,
4500
+ 'img.ok': OK_SVG,
4501
+ 'img.okDis': OK_SVG_DISABLED,
4502
+ 'img.cancel': CANCEL_SVG,
4503
+ 'span.warn': {[MARGIN]: rem(2, 0.25), [COLOR]: '#d81b60'},
3336
4504
  },
3337
- (style, selector) => (style ? `#${UNIQUE_ID} ${selector}{${style}}` : ''),
4505
+ (style, selector) =>
4506
+ `#${UNIQUE_ID} ${selector}{${arrayJoin(
4507
+ objToArray(style, (value, property) => `${property}:${value};`),
4508
+ )}}`,
3338
4509
  ),
3339
4510
  );
3340
4511
 
3341
- const Inspector = ({position = 'right', open = false}) => {
4512
+ const Inspector = ({position = 'right', open = false, hue = 270}) => {
3342
4513
  const s = useCreateStore(createStore);
3343
4514
  const index = POSITIONS.indexOf(position);
3344
4515
  useCreatePersister(
@@ -3365,7 +4536,9 @@ const Inspector = ({position = 'right', open = false}) => {
3365
4536
  /* @__PURE__ */ jsx(Panel, {s}),
3366
4537
  ],
3367
4538
  }),
3368
- /* @__PURE__ */ jsx('style', {children: APP_STYLESHEET}),
4539
+ /* @__PURE__ */ jsxs('style', {
4540
+ children: [`#${UNIQUE_ID}{--hue:${hue}}`, APP_STYLESHEET],
4541
+ }),
3369
4542
  ],
3370
4543
  });
3371
4544
  };