kaafil-react-uikit 0.1.0 → 0.3.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.
- package/dist/admin/index.cjs +342 -342
- package/dist/admin/index.js +5 -5
- package/dist/{chunk-YHOQRKDJ.cjs → chunk-57SUK3GD.cjs} +7 -7
- package/dist/{chunk-YHOQRKDJ.cjs.map → chunk-57SUK3GD.cjs.map} +1 -1
- package/dist/{chunk-2SRBJ4H7.js → chunk-A4Z2YBEF.js} +19 -5
- package/dist/chunk-A4Z2YBEF.js.map +1 -0
- package/dist/{chunk-2MWTLYVP.cjs → chunk-BBC5EX5O.cjs} +17 -17
- package/dist/{chunk-2MWTLYVP.cjs.map → chunk-BBC5EX5O.cjs.map} +1 -1
- package/dist/{chunk-W5PG3IUJ.cjs → chunk-ECCQW5LN.cjs} +7 -4
- package/dist/chunk-ECCQW5LN.cjs.map +1 -0
- package/dist/{chunk-M2D6CZK2.cjs → chunk-FVK7HMQ5.cjs} +37 -37
- package/dist/{chunk-M2D6CZK2.cjs.map → chunk-FVK7HMQ5.cjs.map} +1 -1
- package/dist/{chunk-PYETPKTT.js → chunk-GJ2J3PYN.js} +3 -3
- package/dist/{chunk-PYETPKTT.js.map → chunk-GJ2J3PYN.js.map} +1 -1
- package/dist/{chunk-TF3GCIDK.cjs → chunk-HACH2NUM.cjs} +24 -13
- package/dist/chunk-HACH2NUM.cjs.map +1 -0
- package/dist/{chunk-PDQVVJCS.js → chunk-KW5LH6KV.js} +3 -3
- package/dist/{chunk-PDQVVJCS.js.map → chunk-KW5LH6KV.js.map} +1 -1
- package/dist/{chunk-WS2DKREI.cjs → chunk-MNUCVVIE.cjs} +168 -97
- package/dist/chunk-MNUCVVIE.cjs.map +1 -0
- package/dist/{chunk-CURTZGHY.js → chunk-RWLO6IFX.js} +19 -8
- package/dist/chunk-RWLO6IFX.js.map +1 -0
- package/dist/{chunk-V36WWMTF.cjs → chunk-UALMCHNW.cjs} +19 -5
- package/dist/chunk-UALMCHNW.cjs.map +1 -0
- package/dist/{chunk-JMWXQTE3.js → chunk-VLP323AD.js} +6 -3
- package/dist/chunk-VLP323AD.js.map +1 -0
- package/dist/{chunk-7WXE5SUS.js → chunk-WTTGPWMR.js} +92 -21
- package/dist/chunk-WTTGPWMR.js.map +1 -0
- package/dist/{chunk-PCDEJHWL.cjs → chunk-YNHOPYBK.cjs} +12 -12
- package/dist/{chunk-PCDEJHWL.cjs.map → chunk-YNHOPYBK.cjs.map} +1 -1
- package/dist/{chunk-FFXGZZGJ.js → chunk-YTSYRLGS.js} +5 -5
- package/dist/{chunk-FFXGZZGJ.js.map → chunk-YTSYRLGS.js.map} +1 -1
- package/dist/{chunk-E42K6UMM.js → chunk-YU2242AR.js} +5 -5
- package/dist/{chunk-E42K6UMM.js.map → chunk-YU2242AR.js.map} +1 -1
- package/dist/core/index.cjs +113 -113
- package/dist/core/index.js +11 -11
- package/dist/manager/index.cjs +239 -239
- package/dist/manager/index.js +6 -6
- package/dist/traveller/index.cjs +35 -35
- package/dist/traveller/index.js +5 -5
- package/package.json +2 -2
- package/dist/chunk-2SRBJ4H7.js.map +0 -1
- package/dist/chunk-7WXE5SUS.js.map +0 -1
- package/dist/chunk-CURTZGHY.js.map +0 -1
- package/dist/chunk-JMWXQTE3.js.map +0 -1
- package/dist/chunk-TF3GCIDK.cjs.map +0 -1
- package/dist/chunk-V36WWMTF.cjs.map +0 -1
- package/dist/chunk-W5PG3IUJ.cjs.map +0 -1
- package/dist/chunk-WS2DKREI.cjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OfflineEngineContext } from './chunk-
|
|
1
|
+
import { OfflineEngineContext } from './chunk-A4Z2YBEF.js';
|
|
2
2
|
import { useContext, useState, useRef, useEffect } from 'react';
|
|
3
3
|
|
|
4
4
|
var TICK_INTERVAL_MS = 1e3;
|
|
@@ -12,6 +12,9 @@ function useServerTime() {
|
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
14
|
const unsubscribe = engine.events.on("snapshot.updated", (event) => {
|
|
15
|
+
if (event.serverTime === void 0) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
15
18
|
observedAtPerfRef.current = performance.now();
|
|
16
19
|
setLastServerTime(event.serverTime);
|
|
17
20
|
});
|
|
@@ -34,5 +37,5 @@ function useServerTime() {
|
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
export { useServerTime };
|
|
37
|
-
//# sourceMappingURL=chunk-
|
|
38
|
-
//# sourceMappingURL=chunk-
|
|
40
|
+
//# sourceMappingURL=chunk-VLP323AD.js.map
|
|
41
|
+
//# sourceMappingURL=chunk-VLP323AD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/hooks/useServerTime.ts"],"names":[],"mappings":";;;AA8BA,IAAM,gBAAA,GAAmB,GAAA;AAElB,SAAS,aAAA,GAA+B;AAC7C,EAAA,MAAM,MAAA,GAAS,WAAW,oBAAoB,CAAA;AAC9C,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAI,SAA6B,MAAS,CAAA;AAClF,EAAA,MAAM,iBAAA,GAAoB,OAA2B,MAAS,CAAA;AAC9D,EAAA,MAAM,GAAG,SAAS,CAAA,GAAI,SAAS,CAAC,CAAA;AAEhC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,WAAW,IAAA,EAAM;AACnB,MAAA;AAAA,IACF;AAKA,IAAA,MAAM,cAAc,MAAA,CAAO,MAAA,CAAO,EAAA,CAAG,kBAAA,EAAoB,CAAC,KAAA,KAAU;AASlE,MAAA,IAAI,KAAA,CAAM,eAAe,MAAA,EAAW;AAClC,QAAA;AAAA,MACF;AACA,MAAA,iBAAA,CAAkB,OAAA,GAAU,YAAY,GAAA,EAAI;AAC5C,MAAA,iBAAA,CAAkB,MAAM,UAAU,CAAA;AAAA,IACpC,CAAC,CAAA;AACD,IAAA,OAAO,WAAA;AAAA,EACT,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,EAAA,GAAK,YAAY,MAAM,SAAA,CAAU,CAAC,IAAA,KAAS,IAAA,GAAO,CAAC,CAAA,EAAG,gBAAgB,CAAA;AAC5E,IAAA,OAAO,MAAM,cAAc,EAAE,CAAA;AAAA,EAC/B,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,SAAS,GAAA,GAAc;AACrB,IAAA,IAAI,cAAA,KAAmB,MAAA,IAAa,iBAAA,CAAkB,OAAA,KAAY,MAAA,EAAW;AAY3E,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OAEF;AAAA,IACF;AACA,IAAA,MAAM,SAAA,GAAY,WAAA,CAAY,GAAA,EAAI,GAAI,iBAAA,CAAkB,OAAA;AACxD,IAAA,OAAO,IAAI,KAAK,IAAA,CAAK,KAAA,CAAM,cAAc,CAAA,GAAI,SAAS,EAAE,WAAA,EAAY;AAAA,EACtE;AAEA,EAAA,OAAO,EAAE,GAAA,EAAK,aAAA,EAAe,cAAA,EAAe;AAC9C","file":"chunk-VLP323AD.js","sourcesContent":["'use client';\n\n// `08-core-hooks.md §1.6`. The single place that turns the stream of\n// `meta.serverTime` stamps into a usable clock, so no composite reads\n// `meta.serverTime` off an individual response by hand.\n//\n// Hard rule #6 (\"Zero `Date.now()`/`new Date()` local getters in\n// `src/core`\") bans exactly the two calls that fabricate \"now\" from the\n// local wall clock: `Date.now()` and no-argument `new Date()`. This file\n// never calls either. Advancing a SERVER-supplied timestamp by an elapsed\n// delta necessarily needs SOME measure of \"how much local time passed\" —\n// this file measures that with `performance.now()`, a monotonic clock with\n// no relationship to wall-clock \"now\" (it cannot be read as a date, only as\n// a duration), and applies the delta with `new Date(<epoch-ms>)` /\n// `Date.parse(<iso-string>)` — both single-argument forms that operate on a\n// value already anchored to `meta.serverTime`, never on the local clock.\n\nimport { useContext, useEffect, useRef, useState } from 'react';\nimport { OfflineEngineContext } from '../internal/contexts';\n\nexport interface ServerTimeApi {\n now: () => string;\n sinceLastSync: string | undefined;\n}\n\n/** Re-renders any hook consumer often enough for a mounted countdown to look\n * live, without pretending the underlying value moved forward on its own\n * merits (`08-core-hooks.md §1.6`'s sandbox time-travel caveat: this timer\n * forces a re-render, it never advances the stamp past what the last real\n * response justified). */\nconst TICK_INTERVAL_MS = 1000;\n\nexport function useServerTime(): ServerTimeApi {\n const engine = useContext(OfflineEngineContext);\n const [lastServerTime, setLastServerTime] = useState<string | undefined>(undefined);\n const observedAtPerfRef = useRef<number | undefined>(undefined);\n const [, forceTick] = useState(0);\n\n useEffect(() => {\n if (engine === null) {\n return;\n }\n // `snapshot.updated` is the one event in `OfflineEventMap` that carries\n // `serverTime` (`kaafil-js/src/offline/events.ts`, verified this\n // session) — the engine's other five events do not, so this is the only\n // subscription this hook can build without inventing a stamp.\n const unsubscribe = engine.events.on('snapshot.updated', (event) => {\n // `serverTime` is ABSENT on a change that never involved the server —\n // an optimistic create painted while offline, or an op the host\n // discarded (`kaafil-js/src/offline/events.ts`). Those are real snapshot\n // changes and a list must repaint for them, but they carry no reading,\n // and taking `undefined` here would erase the last real one this\n // session had: `now()` would start throwing again mid-session, on a\n // device that HAS heard from the server, because the manager ticked\n // something off out of signal.\n if (event.serverTime === undefined) {\n return;\n }\n observedAtPerfRef.current = performance.now();\n setLastServerTime(event.serverTime);\n });\n return unsubscribe;\n }, [engine]);\n\n useEffect(() => {\n const id = setInterval(() => forceTick((tick) => tick + 1), TICK_INTERVAL_MS);\n return () => clearInterval(id);\n }, []);\n\n function now(): string {\n if (lastServerTime === undefined || observedAtPerfRef.current === undefined) {\n // No response has ever landed in this session yet. Fabricating a\n // value from the local wall clock is exactly what hard rule #6\n // forbids — this is the one case this hook cannot silently satisfy\n // its own non-optional return type, so it says so loudly instead.\n // CALLERS: this is a real, expected window — React runs an effect\n // (which is how this hook's own subscription above starts) strictly\n // AFTER the render that needs `now()`'s result has already committed,\n // so a component's very FIRST render can hit this throw even when\n // wired up correctly. Guard the call site, matching\n // `useStaleness.ts`'s own precedent, rather than reaching for a\n // device-clock fallback here (hard rule #6 forbids exactly that).\n throw new Error(\n 'useServerTime().now() was called before any response carrying meta.serverTime ' +\n 'had been observed — there is no server timestamp yet to advance from.',\n );\n }\n const elapsedMs = performance.now() - observedAtPerfRef.current;\n return new Date(Date.parse(lastServerTime) + elapsedMs).toISOString();\n }\n\n return { now, sinceLastSync: lastServerTime };\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OfflineEngineContext, KaafilClientContext, useCapabilityRows, UNKNOWN_CAPABILITY_TRIPLE, deriveCapabilityTriple, darkReasonFor, useKaafilClient, useOfflineMutation, usePersona, isDevelopment, useOfflineEvent } from './chunk-
|
|
1
|
+
import { OfflineEngineContext, KaafilClientContext, useCapabilityRows, UNKNOWN_CAPABILITY_TRIPLE, deriveCapabilityTriple, darkReasonFor, useKaafilClient, useOfflineMutation, usePersona, isDevelopment, useOfflineEvent } from './chunk-A4Z2YBEF.js';
|
|
2
2
|
import { UnsatisfiableSchemeError, isKaafilError, SyncOpMethod } from 'kaafil-js/client';
|
|
3
3
|
export { FALLBACK_GLYPH, SHADES_PER_FAMILY, TONE_FAMILIES, parseRoomingTone, roomingHeuristicSeverity } from 'kaafil-js/client';
|
|
4
4
|
import { useContext, useState, useRef, useCallback, useEffect } from 'react';
|
|
@@ -176,6 +176,14 @@ function createDomainHook(moduleKey, build) {
|
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
// src/core/hooks/useChecklists.ts
|
|
179
|
+
function appendPendingRows(fromAggregate, fromSnapshot) {
|
|
180
|
+
if (fromSnapshot.length === 0) {
|
|
181
|
+
return fromAggregate;
|
|
182
|
+
}
|
|
183
|
+
const known = new Set(fromAggregate.map((row) => row.id));
|
|
184
|
+
const pending = fromSnapshot.filter((row) => !known.has(row.id));
|
|
185
|
+
return pending.length === 0 ? fromAggregate : [...fromAggregate, ...pending];
|
|
186
|
+
}
|
|
179
187
|
var useChecklistsInternal = createDomainHook("checklists", (tripRef) => {
|
|
180
188
|
const client = useKaafilClient();
|
|
181
189
|
const engine = useContext(OfflineEngineContext);
|
|
@@ -183,22 +191,31 @@ var useChecklistsInternal = createDomainHook("checklists", (tripRef) => {
|
|
|
183
191
|
tripRef,
|
|
184
192
|
"checklist"
|
|
185
193
|
);
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
194
|
+
const aggregateCacheKey = `checklists.read:${tripRef}`;
|
|
195
|
+
const [aggregate, setAggregate] = useState(() => {
|
|
196
|
+
const cached = engine?.reads.get(
|
|
197
|
+
aggregateCacheKey
|
|
198
|
+
);
|
|
199
|
+
if (cached !== void 0) {
|
|
200
|
+
return { ...cached.value, loaded: true, lastFetchFailed: false };
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
title: void 0,
|
|
204
|
+
subtitle: void 0,
|
|
205
|
+
progress: void 0,
|
|
206
|
+
hasOpenMandatoryByPhase: void 0,
|
|
207
|
+
sections: [],
|
|
208
|
+
items: [],
|
|
209
|
+
availableTemplates: [],
|
|
210
|
+
loaded: false,
|
|
211
|
+
lastFetchFailed: false,
|
|
212
|
+
fetchedAt: void 0
|
|
213
|
+
};
|
|
197
214
|
});
|
|
198
215
|
const refreshAggregate = useCallback(async () => {
|
|
199
216
|
try {
|
|
200
217
|
const response = await client.checklists.read({ tripRef });
|
|
201
|
-
|
|
218
|
+
const value = {
|
|
202
219
|
title: response.title,
|
|
203
220
|
subtitle: response.subtitle,
|
|
204
221
|
progress: response.progress,
|
|
@@ -206,14 +223,21 @@ var useChecklistsInternal = createDomainHook("checklists", (tripRef) => {
|
|
|
206
223
|
sections: response.sections,
|
|
207
224
|
items: response.items,
|
|
208
225
|
availableTemplates: response.availableTemplates,
|
|
209
|
-
loaded: true,
|
|
210
|
-
lastFetchFailed: false,
|
|
211
226
|
fetchedAt: response.meta.serverTime
|
|
227
|
+
};
|
|
228
|
+
void engine?.reads.set(aggregateCacheKey, value, response.meta.serverTime).catch(() => {
|
|
212
229
|
});
|
|
230
|
+
setAggregate({ ...value, loaded: true, lastFetchFailed: false });
|
|
213
231
|
} catch {
|
|
214
|
-
setAggregate((previous) =>
|
|
232
|
+
setAggregate((previous) => {
|
|
233
|
+
if (previous.loaded) {
|
|
234
|
+
return { ...previous, lastFetchFailed: true };
|
|
235
|
+
}
|
|
236
|
+
const cached = engine?.reads.get(aggregateCacheKey);
|
|
237
|
+
return cached === void 0 ? { ...previous, lastFetchFailed: true } : { ...cached.value, loaded: true, lastFetchFailed: true };
|
|
238
|
+
});
|
|
215
239
|
}
|
|
216
|
-
}, [client, tripRef]);
|
|
240
|
+
}, [client, tripRef, engine, aggregateCacheKey]);
|
|
217
241
|
useEffect(() => {
|
|
218
242
|
void refreshAggregate();
|
|
219
243
|
}, [refreshAggregate]);
|
|
@@ -233,7 +257,54 @@ var useChecklistsInternal = createDomainHook("checklists", (tripRef) => {
|
|
|
233
257
|
method: SyncOpMethod.Post,
|
|
234
258
|
path: `/api/v1/trips/${tripRef}/checklist/items`,
|
|
235
259
|
operationId: "addChecklistItem",
|
|
236
|
-
body: input
|
|
260
|
+
body: input,
|
|
261
|
+
// ── THE OPTIMISTIC CREATE ──────────────────────────────────────
|
|
262
|
+
// Without this the item a manager adds out of signal does not
|
|
263
|
+
// appear until it syncs. It was queued, durable and landed on
|
|
264
|
+
// reconnect the whole time — and from where the manager is
|
|
265
|
+
// standing, work that does not show up is work that was lost, so
|
|
266
|
+
// they add it again.
|
|
267
|
+
//
|
|
268
|
+
// `creates` makes the ENGINE mint the row's temporary id (this
|
|
269
|
+
// hook never invents identifiers) and swap it for the server's
|
|
270
|
+
// canonical row the moment the write lands, in one
|
|
271
|
+
// `snapshot.updated`, so the item is never rendered twice.
|
|
272
|
+
creates: true,
|
|
273
|
+
entity: { listName: "checklist" },
|
|
274
|
+
// Shaped as a real `ChecklistItemDeltaRow` so the board renders it
|
|
275
|
+
// through the same path as every other row rather than a special
|
|
276
|
+
// "pending" branch. `id` is a placeholder the engine replaces with
|
|
277
|
+
// the id it mints; `version: 0` cannot beat any server row in the
|
|
278
|
+
// snapshot's version-guarded merge.
|
|
279
|
+
//
|
|
280
|
+
// The write addresses a section by its `sectionKey`, but the board
|
|
281
|
+
// groups rows by `sectionId`, so the id is resolved from the sections
|
|
282
|
+
// this hook already holds. Adding to a section that does not exist
|
|
283
|
+
// yet resolves to `''` and the row sits ungrouped until the write
|
|
284
|
+
// lands — correct rather than clever: inventing a section id would
|
|
285
|
+
// put the item under a heading that does not exist.
|
|
286
|
+
optimistic: {
|
|
287
|
+
id: "pending",
|
|
288
|
+
version: 0,
|
|
289
|
+
sectionId: aggregate.sections.find((section) => section.key === input.sectionKey)?.id ?? "",
|
|
290
|
+
key: input.key ?? null,
|
|
291
|
+
title: input.title,
|
|
292
|
+
subLine: null,
|
|
293
|
+
status: "OPEN",
|
|
294
|
+
// `=== true`, never `?? false` (hard rule #5): an omitted
|
|
295
|
+
// `mandatory` is the SERVER's default to apply, not this hook's to
|
|
296
|
+
// guess. The optimistic row shows it unstarred for the moment it
|
|
297
|
+
// takes the write to land, and the canonical row replaces it.
|
|
298
|
+
isMandatory: input.mandatory === true,
|
|
299
|
+
gate: null,
|
|
300
|
+
dayOffset: null,
|
|
301
|
+
sortOrder: Number.MAX_SAFE_INTEGER,
|
|
302
|
+
completedByManagerId: null,
|
|
303
|
+
performedByKind: null,
|
|
304
|
+
performedById: null,
|
|
305
|
+
completedAt: null,
|
|
306
|
+
updatedAt: null
|
|
307
|
+
}
|
|
237
308
|
}),
|
|
238
309
|
// ── THE DESK LANE ─────────────────────────────────────────────────
|
|
239
310
|
// All five checklist writes take the admin triple, and a desk console
|
|
@@ -375,7 +446,7 @@ var useChecklistsInternal = createDomainHook("checklists", (tripRef) => {
|
|
|
375
446
|
(input) => client.checklists.agencyTemplates.publish(input),
|
|
376
447
|
[client]
|
|
377
448
|
);
|
|
378
|
-
const items = syncedAt === void 0 ? aggregate.items : snapshotItems;
|
|
449
|
+
const items = syncedAt === void 0 ? appendPendingRows(aggregate.items, snapshotItems) : snapshotItems;
|
|
379
450
|
return {
|
|
380
451
|
items,
|
|
381
452
|
syncedAt,
|
|
@@ -2150,5 +2221,5 @@ function useVendors(tripRef, agencyRef) {
|
|
|
2150
2221
|
}
|
|
2151
2222
|
|
|
2152
2223
|
export { ERROR_HANDLING_PATH, FORM_FIELD_KIND_SINGLE_BOOLEAN, classifyError, createDomainHook, useChecklists, useCloseout, useCollections, useExpenses, useFiles, useFloat, useForms, useItinerary, useManagerToday, useManagers, useParties, usePickups, useRooming, useSeating, useSnapshotList, useTravellerProfile, useVendors };
|
|
2153
|
-
//# sourceMappingURL=chunk-
|
|
2154
|
-
//# sourceMappingURL=chunk-
|
|
2224
|
+
//# sourceMappingURL=chunk-WTTGPWMR.js.map
|
|
2225
|
+
//# sourceMappingURL=chunk-WTTGPWMR.js.map
|