@declarion/react 0.2.7 → 0.2.9
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-lib/{DraggableChildrenTable-BKQNXZdc.js → DraggableChildrenTable-BJ3W4Wxm.js} +30 -30
- package/dist-lib/{DraggableChildrenTable-BKQNXZdc.js.map → DraggableChildrenTable-BJ3W4Wxm.js.map} +1 -1
- package/dist-lib/{Grid-pE2-dvug.js → Grid-POpRhlPk.js} +2 -2
- package/dist-lib/{Grid-pE2-dvug.js.map → Grid-POpRhlPk.js.map} +1 -1
- package/dist-lib/{MarkdownRenderer-Dl3GDuY9.js → MarkdownRenderer-bs52XQ7M.js} +15 -12
- package/dist-lib/MarkdownRenderer-bs52XQ7M.js.map +1 -0
- package/dist-lib/api/auth.d.ts +1 -1
- package/dist-lib/components/primitives/ClassifiedFieldLocked.d.ts +10 -0
- package/dist-lib/components/primitives/Icons.d.ts +1 -0
- package/dist-lib/components/primitives/index.d.ts +1 -0
- package/dist-lib/{dataTableStyles-4q9A0Djy.js → dataTableStyles-DctG2tMU.js} +625 -606
- package/dist-lib/dataTableStyles-DctG2tMU.js.map +1 -0
- package/dist-lib/declarion-react.css +1 -1
- package/dist-lib/hooks/useAuth.d.ts +1 -0
- package/dist-lib/index.d.ts +3 -0
- package/dist-lib/index.js +5196 -4878
- package/dist-lib/index.js.map +1 -1
- package/dist-lib/lib/field-classification.d.ts +52 -0
- package/dist-lib/lib/sort.d.ts +72 -0
- package/dist-lib/types/schema.d.ts +65 -0
- package/dist-lib/{value-qao1rdkR.js → value-CXFBdyeL.js} +10 -9
- package/dist-lib/{value-qao1rdkR.js.map → value-CXFBdyeL.js.map} +1 -1
- package/package.json +1 -1
- package/dist-lib/MarkdownRenderer-Dl3GDuY9.js.map +0 -1
- package/dist-lib/dataTableStyles-4q9A0Djy.js.map +0 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Entity, FieldAccessInfo, ClassificationTierDef, Schema } from "../types/schema";
|
|
2
|
+
/**
|
|
3
|
+
* isFieldReadable returns true when the caller can see the field's
|
|
4
|
+
* value. Non-classified fields are always readable (no entry in
|
|
5
|
+
* field_access). Classified fields are readable when field_access
|
|
6
|
+
* marks read="granted". Plan §B9.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isFieldReadable(entity: Entity | undefined, fieldName: string): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* isFieldWritable returns true when the caller can submit a new value
|
|
11
|
+
* for the field. Form components disable input + show a lock badge
|
|
12
|
+
* when this returns false. Non-classified fields are always writable
|
|
13
|
+
* (gating happens via entity-level RBAC at the HTTP layer). Plan §B9.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isFieldWritable(entity: Entity | undefined, fieldName: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* fieldClassification returns the classification tier code gating
|
|
18
|
+
* the field, or undefined when the field is non-classified. Lets
|
|
19
|
+
* UI code render a tier badge without re-implementing the field_access
|
|
20
|
+
* lookup.
|
|
21
|
+
*/
|
|
22
|
+
export declare function fieldClassification(entity: Entity | undefined, fieldName: string): string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* fieldRequiredPermission returns the exact grant string an
|
|
25
|
+
* administrator must add to a role to unlock the field for the
|
|
26
|
+
* current caller. Returns undefined when the field is readable +
|
|
27
|
+
* writable (no hint needed). Plan §B9 — operator hand-off surface.
|
|
28
|
+
*/
|
|
29
|
+
export declare function fieldRequiredPermission(entity: Entity | undefined, fieldName: string): string | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* classificationTier returns the localized tier metadata for a field
|
|
32
|
+
* (display name, description, audit_on_read flag, icon). Resolves
|
|
33
|
+
* via the top-level schema.classifications map. Returns undefined when
|
|
34
|
+
* the field is non-classified or the tier code is unknown in the
|
|
35
|
+
* catalog (defense — points at a misconfigured registry).
|
|
36
|
+
*/
|
|
37
|
+
export declare function classificationTier(schema: Schema | undefined, entity: Entity | undefined, fieldName: string): ClassificationTierDef | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* isFieldSoDProtected reports whether the field's tier carries
|
|
40
|
+
* sod_protected:true in the catalog. Used by UI to surface a stronger
|
|
41
|
+
* visual treatment (e.g. red lock vs. grey lock) for tiers that
|
|
42
|
+
* trigger the stricter SoD controls (superadmin-bypass-disabled
|
|
43
|
+
* tenants, role self-assignment refusal, etc).
|
|
44
|
+
*/
|
|
45
|
+
export declare function isFieldSoDProtected(schema: Schema | undefined, entity: Entity | undefined, fieldName: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* fieldAccessInfo returns the raw FieldAccessInfo entry for a field,
|
|
48
|
+
* or undefined when the field is non-classified. Convenience for
|
|
49
|
+
* components that need the full structure (e.g. a tooltip rendering
|
|
50
|
+
* both classification name + required_permission hint).
|
|
51
|
+
*/
|
|
52
|
+
export declare function fieldAccessInfo(entity: Entity | undefined, fieldName: string): FieldAccessInfo | undefined;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export type SortDir = "asc" | "desc";
|
|
2
|
+
export type SortNulls = "first" | "last";
|
|
3
|
+
export interface SortCol {
|
|
4
|
+
field: string;
|
|
5
|
+
dir: SortDir;
|
|
6
|
+
nulls?: SortNulls;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Parse a sort expression string into a list of SortCol entries.
|
|
10
|
+
*
|
|
11
|
+
* Tolerant per plan §5.2:
|
|
12
|
+
* - empty/null/undefined → []
|
|
13
|
+
* - missing direction defaults to "asc"
|
|
14
|
+
* - missing nulls segment is left undefined (system default applies server-side)
|
|
15
|
+
* - unknown nulls literal is dropped (server is the strict authority)
|
|
16
|
+
* - empty fields between commas are skipped
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseSort(s: string | null | undefined): SortCol[];
|
|
19
|
+
/**
|
|
20
|
+
* Filter a raw sort URL string so $property.* segments (deferred per plan §2)
|
|
21
|
+
* don't reach the backend's strict parser. EVERY OTHER token passes through
|
|
22
|
+
* unchanged - including malformed grammar like `:nulls_middle` or extra
|
|
23
|
+
* colons - so the backend can return a typed ValidationError and the SDK
|
|
24
|
+
* surfaces the error to the user. Plan §14 strict-parse contract requires
|
|
25
|
+
* that grammar violations are NOT silently rewritten on the client.
|
|
26
|
+
*/
|
|
27
|
+
export declare function stripUnsupportedSortSegments(s: string | null | undefined): string | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Serialize a list of SortCol entries back to the canonical string form.
|
|
30
|
+
* Round-trips losslessly with parseSort for any valid input.
|
|
31
|
+
*/
|
|
32
|
+
export declare function serializeSort(cols: SortCol[]): string;
|
|
33
|
+
/**
|
|
34
|
+
* Server-enforced cap (plan §3 Decision 4, §4.2). Mirrored on the client so
|
|
35
|
+
* we never POST a sort the server will reject with HTTP 400.
|
|
36
|
+
*/
|
|
37
|
+
export declare const MAX_SORT_COLS = 5;
|
|
38
|
+
/**
|
|
39
|
+
* Shift-click on a column header (plan §7.1).
|
|
40
|
+
*
|
|
41
|
+
* - field already in `prev` → remove it (toggle off).
|
|
42
|
+
* - field not in `prev` → append { field, dir: "asc" } to the tail.
|
|
43
|
+
*
|
|
44
|
+
* When the list is already at the {@link MAX_SORT_COLS} cap AND `field` is
|
|
45
|
+
* not already in it, the helper refuses and returns `prev` unchanged. The
|
|
46
|
+
* UI surfaces this implicitly: the "Add to multi-sort" menu item is hidden
|
|
47
|
+
* once the cap is reached, and a shift-click on a brand-new column at the
|
|
48
|
+
* cap is a no-op (consistent UX, matches the brief's "refuse" call).
|
|
49
|
+
*
|
|
50
|
+
* Nulls placement of every retained column is preserved verbatim - shift-
|
|
51
|
+
* click never silently rewrites another column's NULL setting.
|
|
52
|
+
*
|
|
53
|
+
* Returned arrays are always new references; never mutates `prev`.
|
|
54
|
+
*/
|
|
55
|
+
export declare function applyShiftClickSort(prev: SortCol[], field: string): SortCol[];
|
|
56
|
+
/**
|
|
57
|
+
* "Add to multi-sort" menu action (plan §7.2). Adds `col` to the sort tail
|
|
58
|
+
* with the caller-chosen `dir` + `nulls`. Dedupes: if `col.field` is already
|
|
59
|
+
* present in `prev`, the earlier occurrence is removed and the new one
|
|
60
|
+
* appended at the tail (server rejects duplicate fields, plan §4.2).
|
|
61
|
+
*
|
|
62
|
+
* Refuses to grow past {@link MAX_SORT_COLS}: when appending would exceed
|
|
63
|
+
* the cap AND the field is not already present, returns `prev` unchanged.
|
|
64
|
+
* The menu item that drives this is hidden at the cap, so this guard exists
|
|
65
|
+
* to keep the helper safe under any caller.
|
|
66
|
+
*/
|
|
67
|
+
export declare function applyAppendSort(prev: SortCol[], col: SortCol): SortCol[];
|
|
68
|
+
/**
|
|
69
|
+
* "Clear sort on this column" menu action (plan §7.2). Removes the one
|
|
70
|
+
* entry matching `field` from `prev`; returns `prev` unchanged if absent.
|
|
71
|
+
*/
|
|
72
|
+
export declare function removeSortField(prev: SortCol[], field: string): SortCol[];
|
|
@@ -98,6 +98,34 @@ export interface EntityField {
|
|
|
98
98
|
structure?: string;
|
|
99
99
|
array?: boolean;
|
|
100
100
|
copyable?: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Plan 2026-05-26 §4 / B13. Names the data_classifications tier
|
|
103
|
+
* gating reads + writes on this field. Read-side: stripped from the
|
|
104
|
+
* row when the caller lacks `classification:<tier>:read`. Write-side:
|
|
105
|
+
* 422 FIELDS_FORBIDDEN when the caller writes the key without
|
|
106
|
+
* `classification:<tier>:write`. Frontend reads the tier's localized
|
|
107
|
+
* display name from the top-level `classifications:` map and
|
|
108
|
+
* cross-references `schema.entities.<code>.field_access.<field>` for
|
|
109
|
+
* the per-caller decision.
|
|
110
|
+
*/
|
|
111
|
+
classification?: string;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Per-caller classification decision for one classified field on one
|
|
115
|
+
* entity. Plan 2026-05-26 §8 / B9. Populated by the schema endpoint
|
|
116
|
+
* from the caller's grants + authority tier; the frontend reads this
|
|
117
|
+
* to render the locked-widget badge ("🔒 Compensation"), disable write
|
|
118
|
+
* inputs, and surface the operator-facing `required_permission` hint
|
|
119
|
+
* to the user (e.g. "Ask your admin to grant you
|
|
120
|
+
* classification:compensation:read").
|
|
121
|
+
*/
|
|
122
|
+
export interface FieldAccessInfo {
|
|
123
|
+
read: "granted" | "denied";
|
|
124
|
+
write: "granted" | "denied";
|
|
125
|
+
classification: string;
|
|
126
|
+
/** Only set when read OR write is denied — the exact grant string an
|
|
127
|
+
* administrator needs to add to a role to unlock this field. */
|
|
128
|
+
required_permission?: string;
|
|
101
129
|
}
|
|
102
130
|
export interface StructureDef {
|
|
103
131
|
name: LocalizedString;
|
|
@@ -283,6 +311,16 @@ export interface Entity {
|
|
|
283
311
|
* Server delivers RBAC-pruned nodes in tagged-union wire format (plan §8).
|
|
284
312
|
*/
|
|
285
313
|
action_layout?: ActionLayoutNode[];
|
|
314
|
+
/**
|
|
315
|
+
* Plan 2026-05-26 §B9 / §B13. Per-caller classification access
|
|
316
|
+
* decision keyed by field name. Only present for entities that
|
|
317
|
+
* declare at least one classified field; absent on non-classification
|
|
318
|
+
* entities so the wire stays byte-equivalent for non-classification
|
|
319
|
+
* deployments. Frontend reads this map to render the locked-widget
|
|
320
|
+
* badge, disable write inputs, and surface the required_permission
|
|
321
|
+
* hint to the user.
|
|
322
|
+
*/
|
|
323
|
+
field_access?: Record<string, FieldAccessInfo>;
|
|
286
324
|
/**
|
|
287
325
|
* Per-entity realtime opt-in. When true the entity is in the CDC
|
|
288
326
|
* publication, its list views auto-update from the SSE stream, and the
|
|
@@ -763,4 +801,31 @@ export interface Schema {
|
|
|
763
801
|
branding?: Branding;
|
|
764
802
|
areas?: AreaDef[];
|
|
765
803
|
accents?: Record<string, AccentDef>;
|
|
804
|
+
/**
|
|
805
|
+
* Plan 2026-05-26 §B9 / §B13. data_classifications catalog keyed by
|
|
806
|
+
* tier code — display name + description + audit_on_read flag + icon
|
|
807
|
+
* + sod_protected flag. Absent when the consumer declares no tiers
|
|
808
|
+
* (preserves byte-equivalent wire shape for non-classification
|
|
809
|
+
* deployments). Frontend resolves the localized tier name from this
|
|
810
|
+
* map when rendering locked-widget badges.
|
|
811
|
+
*/
|
|
812
|
+
classifications?: Record<string, ClassificationTierDef>;
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Plan 2026-05-26 §B9. One entry in the top-level classifications map.
|
|
816
|
+
* Mirrors engine.DataClassification.
|
|
817
|
+
*/
|
|
818
|
+
export interface ClassificationTierDef {
|
|
819
|
+
name: LocalizedString;
|
|
820
|
+
description?: LocalizedString;
|
|
821
|
+
audit_on_read?: boolean;
|
|
822
|
+
icon?: string;
|
|
823
|
+
/**
|
|
824
|
+
* When true, the tier triggers stricter SoD controls: superadmin
|
|
825
|
+
* reveals emit a distinct audit code, tenant param
|
|
826
|
+
* `auth.superadmin_classification_bypass=false` disables the
|
|
827
|
+
* implicit bypass, role self-assignment is refused, transitive role
|
|
828
|
+
* inheritance is hard-errored at load. Plan §11 Decisions Log #20-22.
|
|
829
|
+
*/
|
|
830
|
+
sod_protected?: boolean;
|
|
766
831
|
}
|
|
@@ -219,32 +219,32 @@ var O = (e) => JSON.stringify(e ?? {}), k = null, A = class extends Error {
|
|
|
219
219
|
constructor(e) {
|
|
220
220
|
super(`refresh failed terminally (${e})`), this.status = e, this.name = "RefreshDeadError";
|
|
221
221
|
}
|
|
222
|
-
}, j = null, M = null,
|
|
223
|
-
function
|
|
222
|
+
}, j = null, M = null, N = 3e4, pe = 5e3;
|
|
223
|
+
function me() {
|
|
224
224
|
F().catch((e) => {
|
|
225
225
|
e instanceof A && I();
|
|
226
226
|
});
|
|
227
227
|
}
|
|
228
|
-
function
|
|
228
|
+
function he(e) {
|
|
229
229
|
if (j &&= (clearTimeout(j), null), M = null, !e || typeof window > "u") return;
|
|
230
230
|
let t = Date.parse(e);
|
|
231
231
|
if (Number.isNaN(t)) return;
|
|
232
232
|
M = t;
|
|
233
|
-
let n = Math.max(t - Date.now() -
|
|
233
|
+
let n = Math.max(t - Date.now() - N, pe);
|
|
234
234
|
j = setTimeout(() => {
|
|
235
|
-
j = null,
|
|
235
|
+
j = null, me();
|
|
236
236
|
}, n);
|
|
237
237
|
}
|
|
238
238
|
function ge() {
|
|
239
239
|
j &&= (clearTimeout(j), null), M = null;
|
|
240
240
|
}
|
|
241
241
|
typeof document < "u" && document.addEventListener("visibilitychange", () => {
|
|
242
|
-
document.visibilityState === "visible" && M !== null && Date.now() >= M -
|
|
242
|
+
document.visibilityState === "visible" && M !== null && Date.now() >= M - N && me();
|
|
243
243
|
});
|
|
244
244
|
async function P(e) {
|
|
245
245
|
try {
|
|
246
246
|
let t = await e.json();
|
|
247
|
-
|
|
247
|
+
he(t?.result?.expires_at ?? t?.expires_at);
|
|
248
248
|
} catch {}
|
|
249
249
|
}
|
|
250
250
|
async function _e() {
|
|
@@ -410,6 +410,7 @@ async function K(e, t, n) {
|
|
|
410
410
|
url: i.url,
|
|
411
411
|
kind: "direct"
|
|
412
412
|
};
|
|
413
|
+
if (!i.url.startsWith(H + "/")) throw Error(`embed file proxy: refusing non-files-route URL ${JSON.stringify(i.url)}`);
|
|
413
414
|
let a = await G(t === "download" ? Ee(i.url) : i.url, n);
|
|
414
415
|
if (!a.ok) throw Error(`embed file proxy fetch failed: ${a.status} ${a.statusText}`);
|
|
415
416
|
let o = await a.blob();
|
|
@@ -763,6 +764,6 @@ function it(e) {
|
|
|
763
764
|
return e ? Array.isArray(e) ? e.filter($) : $(e) ? [e] : [] : [];
|
|
764
765
|
}
|
|
765
766
|
//#endregion
|
|
766
|
-
export { ve as A, g as B, B as C, F as D, ge as E, x as F, m as H, re as I, b as L, fe as M, C as N, L as O, S as P, oe as R, A as S, V as T, p as U, _ as V, c as W, q as _, Xe as a, De as b, Be as c, Ue as d, We as f, Je as g, Re as h, tt as i, E as j,
|
|
767
|
+
export { ve as A, g as B, B as C, F as D, ge as E, x as F, m as H, re as I, b as L, fe as M, C as N, L as O, S as P, oe as R, A as S, V as T, p as U, _ as V, c as W, q as _, Xe as a, De as b, Be as c, Ue as d, We as f, Je as g, Re as h, tt as i, E as j, he as k, He as l, Ke as m, rt as n, Qe as o, Ve as p, nt as r, Ze as s, it as t, qe as u, Me as v, Se as w, Ne as x, Q as y, h as z };
|
|
767
768
|
|
|
768
|
-
//# sourceMappingURL=value-
|
|
769
|
+
//# sourceMappingURL=value-CXFBdyeL.js.map
|