@declarion/react 0.45.0 → 0.48.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.
Files changed (47) hide show
  1. package/dist-lib/{DraggableChildrenTable-BDnJK0AU.js → DraggableChildrenTable-p2ZSdwzj.js} +2 -2
  2. package/dist-lib/{DynamicIcon-DeRpAaXm.js → DynamicIcon-Dc2j-rg_.js} +19 -17
  3. package/dist-lib/{Grid-CcCveEE7.js → Grid-CjLFAKMZ.js} +2 -2
  4. package/dist-lib/{LayoutRenderer-BReuhVdX.js → LayoutRenderer-X3p4yfo_.js} +598 -585
  5. package/dist-lib/{MarkdownRenderer-DPKDFR60.js → MarkdownRenderer-Sb7zcvj0.js} +10 -10
  6. package/dist-lib/{RefreshControl-KddgOhUG.js → RefreshControl-Cnl9nE0x.js} +268 -238
  7. package/dist-lib/{SmartDetailPage.impl-D_hMxiHy.js → SmartDetailPage.impl-bb0UNOII.js} +545 -532
  8. package/dist-lib/{SmartRecordListPage.impl-GIo_mPIJ.js → SmartRecordListPage.impl-BFh8auUZ.js} +171 -158
  9. package/dist-lib/api/agents.d.ts +47 -18
  10. package/dist-lib/components/agents/AgentChatPanel.d.ts +7 -1
  11. package/dist-lib/components/agents/AgentPicker.d.ts +9 -0
  12. package/dist-lib/components/agents/transcript-runs.d.ts +29 -0
  13. package/dist-lib/components/file-widgets/host.d.ts +1 -0
  14. package/dist-lib/components/list/QuickPeek.d.ts +1 -1
  15. package/dist-lib/components/pages/list/ListFloatbar.d.ts +4 -2
  16. package/dist-lib/components/pages/list/cardProjection.d.ts +2 -1
  17. package/dist-lib/components/primitives/Tooltip.d.ts +4 -0
  18. package/dist-lib/components/shared/ResponsiveActionBar.d.ts +10 -5
  19. package/dist-lib/components/shared/RowActionsKebab.d.ts +3 -2
  20. package/dist-lib/components/views/ViewSwitcher.d.ts +2 -1
  21. package/dist-lib/declarion-react.css +1 -1
  22. package/dist-lib/hooks/useAgentConversation.d.ts +10 -24
  23. package/dist-lib/hooks/useBrandingChrome.d.ts +11 -0
  24. package/dist-lib/hooks/useFilters.d.ts +1 -0
  25. package/dist-lib/hooks/useLongPress.d.ts +29 -0
  26. package/dist-lib/hooks/useResponsiveMode.d.ts +2 -21
  27. package/dist-lib/icons.js +1 -1
  28. package/dist-lib/index.d.ts +10 -3
  29. package/dist-lib/index.js +3305 -2741
  30. package/dist-lib/lib/actions.d.ts +13 -5
  31. package/dist-lib/lib/filter-evaluator.d.ts +16 -0
  32. package/dist-lib/lib/filters.d.ts +10 -4
  33. package/dist-lib/lib/longPressGesture.d.ts +55 -0
  34. package/dist-lib/lib/messages.d.ts +1 -0
  35. package/dist-lib/lib/page-inset.d.ts +3 -0
  36. package/dist-lib/lib/variants.d.ts +7 -0
  37. package/dist-lib/lib/viewport-category.d.ts +44 -0
  38. package/dist-lib/{registry-DJKp0yaV.js → registry-CWDnxiLJ.js} +1291 -1008
  39. package/dist-lib/testing.js +10 -10
  40. package/dist-lib/types/api.d.ts +15 -2
  41. package/dist-lib/types/schema.d.ts +26 -0
  42. package/dist-lib/{useCurrentScreen-A3xZDs7U.js → useCurrentScreen-BshVTPVq.js} +1124 -1088
  43. package/dist-lib/{useProperties-TlltWwLv.js → useProperties-B5p9mIH8.js} +92 -61
  44. package/dist-lib/{value-CHY7LgZ-.js → value-B1O6QikE.js} +1 -1
  45. package/dist-lib/vite/index.js +23 -22
  46. package/package.json +12 -12
  47. package/dist-lib/components/agents/AgentVisualHints.d.ts +0 -6
@@ -96,11 +96,19 @@ export declare function actionNeedsConfirm(action: Action | undefined): boolean;
96
96
  * Precedence: disabled-reason > description > name.
97
97
  *
98
98
  * A labeled control already shows the name, so its tooltip is the description
99
- * alone; an icon-only control (`display.icon_only`) has no visible label, so it
100
- * shows "name - description" to keep the name reachable on hover. Absent
101
- * description falls back to the name - byte-identical to pre-description behavior.
99
+ * alone. A control with no visible label - declared `display.icon_only`, or a
100
+ * label the bar dropped to keep the button in a tight row - leads with the NAME
101
+ * on its own line, then the description. Absent description falls back to the
102
+ * name.
102
103
  */
103
- export declare function actionTooltip(action: Action | undefined, name: string, isDisabled: boolean, reason: string | null | undefined): string;
104
+ export declare function actionTooltip(action: Action | undefined, name: string, isDisabled: boolean, reason: string | null | undefined,
105
+ /**
106
+ * True when the button is rendering WITHOUT its label right now - either
107
+ * because the author declared `display.icon_only`, or because the row ran out
108
+ * of width and the bar dropped the label to keep the button. Both cases leave
109
+ * the user looking at an icon, so the tooltip has to say the name first.
110
+ */
111
+ labelHidden?: boolean): string;
104
112
  /**
105
113
  * Builds the full dot-qualified action code for API calls.
106
114
  */
@@ -170,7 +178,7 @@ export type ResolvedActionLayoutNode = ResolvedActionLeaf | ResolvedActionGroup;
170
178
  * @param rowSelection All selected rows for bulk context (list_toolbar bulk mode).
171
179
  * Pass empty array for non-bulk contexts.
172
180
  */
173
- export declare function applyRowState(layout: ResolvedActionLayoutNode[], entityActions: Record<string, Action> | undefined, globalActions: Record<string, Action> | undefined, row: Record<string, unknown>, rowSelection: Record<string, unknown>[]): ResolvedActionLayoutNode[];
181
+ export declare function applyRowState(layout: ResolvedActionLayoutNode[], entityActions: Record<string, Action> | undefined, globalActions: Record<string, Action> | undefined, row: Record<string, unknown>, rowSelection: Record<string, unknown>[], allowedActionCodes?: ReadonlySet<string>): ResolvedActionLayoutNode[];
174
182
  /**
175
183
  * Composes a flat ResolvedActionLayoutNode[] from an entity's actions map,
176
184
  * filtered to those that include the given slot in their visibility array,
@@ -0,0 +1,16 @@
1
+ import type { FilterNode } from "./filters";
2
+ /** Metadata needed to evaluate a record-only filter condition. */
3
+ export interface FilterRecordField {
4
+ type: "string" | "text" | "rich_text" | "email" | "url" | "phone" | "enum" | "int" | "float" | "decimal" | "date" | "timestamp" | "time" | "bool" | "ref" | "uuid" | (string & {});
5
+ }
6
+ export type FilterRecordFields = Readonly<Record<string, FilterRecordField>>;
7
+ export type FilterRecord = Readonly<Record<string, unknown>>;
8
+ /**
9
+ * Evaluate a loader-validated filter tree against one already-loaded record.
10
+ *
11
+ * This deliberately accepts only the deterministic record subset: it has no
12
+ * caller, clock, relation lookup, or value coercion input. A missing field is
13
+ * the same as null for `is_empty`; every other operator returns false for a
14
+ * missing, null, or empty value.
15
+ */
16
+ export declare function evaluateFilterTree(nodes: FilterNode[], fields: FilterRecordFields, record: FilterRecord): boolean;
@@ -4,8 +4,8 @@ export interface FilterNode {
4
4
  field?: string;
5
5
  op?: FilterOp;
6
6
  value?: unknown;
7
- /** OR group: each inner array is AND-ed, groups are OR-ed */
8
- or?: FilterNode[][];
7
+ /** OR group: child nodes are OR-ed. */
8
+ or?: FilterNode[];
9
9
  /** Explicit AND group (rarely needed, top-level is implicit AND) */
10
10
  and?: FilterNode[];
11
11
  }
@@ -39,7 +39,13 @@ export declare const NO_VALUE_OPS: Set<FilterOp>;
39
39
  export declare const MULTI_VALUE_OPS: Set<FilterOp>;
40
40
  /** Human-friendly display names for operators. */
41
41
  export declare const OP_LABELS: Record<FilterOp, string>;
42
+ export interface FilterURLState {
43
+ filters: FilterNode[];
44
+ error: string | null;
45
+ }
42
46
  /** Parse filters from URL search params (JSON `filters` param). */
47
+ export declare function parseFilterURLState(searchParams: URLSearchParams): FilterURLState;
48
+ /** Parse the final tree and reject malformed URL state instead of treating it as no filter. */
43
49
  export declare function parseFiltersFromURL(searchParams: URLSearchParams): FilterNode[];
44
50
  /** Write filters to URL search params. */
45
51
  export declare function setFiltersInURL(filters: FilterNode[], searchParams: URLSearchParams): void;
@@ -48,7 +54,7 @@ export declare function setFiltersInURL(filters: FilterNode[], searchParams: URL
48
54
  * Uses the JSON `filters` param for the API request.
49
55
  */
50
56
  export declare function filtersToApiParams(filters: FilterNode[]): URLSearchParams;
51
- /** Check if the filter tree has any OR groups (needs Level 2 UI). */
57
+ /** Check if the filter tree has any OR groups. */
52
58
  export declare function hasOrGroups(nodes: FilterNode[]): boolean;
53
59
  /** Extract flat field conditions from a FilterNode array (ignoring OR/AND structure). */
54
60
  export declare function flatFieldConditions(nodes: FilterNode[]): FilterNode[];
@@ -67,5 +73,5 @@ export declare function countActiveFilters(nodes: FilterNode[]): number;
67
73
  export declare function formatFilterChip(node: FilterNode, resolveValue?: FilterValueResolver): string;
68
74
  /** Create a simple equality filter node. */
69
75
  export declare function eqFilter(field: string, value: string): FilterNode;
70
- /** Remove a filter node by field name, recursing into OR/AND groups. */
76
+ /** Remove a filter node by field name, recursing through the final tree. */
71
77
  export declare function removeFilter(nodes: FilterNode[], field: string): FilterNode[];
@@ -0,0 +1,55 @@
1
+ /**
2
+ * How long a press is held before it becomes a Row Menu request. 500ms is what
3
+ * Android and iOS both use for their own long-press, so a user's thumb already
4
+ * knows this number.
5
+ */
6
+ export declare const LONG_PRESS_HOLD_MS = 500;
7
+ /**
8
+ * How far the pointer may drift and still be a press. Past this the gesture is a
9
+ * scroll, and a list that opens menus while the user is scrolling it is worse
10
+ * than one with no long-press at all.
11
+ */
12
+ export declare const LONG_PRESS_MOVE_TOLERANCE_PX = 10;
13
+ /** Where a press started. `null` means no press is in progress. */
14
+ export type PressOrigin = {
15
+ x: number;
16
+ y: number;
17
+ } | null;
18
+ export type LongPressInput = {
19
+ type: "down";
20
+ x: number;
21
+ y: number;
22
+ }
23
+ /** Pointer moved, or the surface under it scrolled. */
24
+ | {
25
+ type: "move";
26
+ x: number;
27
+ y: number;
28
+ }
29
+ /** Released, cancelled by the OS, or the element lost the pointer. */
30
+ | {
31
+ type: "release";
32
+ }
33
+ /** The hold timer elapsed. */
34
+ | {
35
+ type: "held";
36
+ };
37
+ export type LongPressOutcome =
38
+ /** A press is in progress; keep the timer running. */
39
+ "pending"
40
+ /** No press is in progress; cancel any timer. */
41
+ | "idle"
42
+ /** Open the Row Menu at the press origin. */
43
+ | "fire";
44
+ export interface LongPressStep {
45
+ origin: PressOrigin;
46
+ outcome: LongPressOutcome;
47
+ }
48
+ /**
49
+ * Advances the gesture. Returns the new origin and what the caller should do.
50
+ *
51
+ * A `held` without an origin cannot fire: the timer is cleared on every exit,
52
+ * but a timer that has already been queued when the press ends would otherwise
53
+ * open a menu after the user let go.
54
+ */
55
+ export declare function stepLongPress(origin: PressOrigin, input: LongPressInput, tolerance?: number): LongPressStep;
@@ -1,5 +1,6 @@
1
1
  import { type LocalizedString } from "../types/schema";
2
2
  import type { PublicParam } from "../types/api";
3
+ export declare const DEFAULT_LOCALE = "en";
3
4
  export type MessageCatalog = Record<string, LocalizedString> | undefined;
4
5
  export declare function localizedMessage(messages: MessageCatalog, code: string, locale: string, fallback?: string): string;
5
6
  export declare function publicLocale(parameters: PublicParam[] | undefined): string;
@@ -0,0 +1,3 @@
1
+ import type { CSSProperties } from "react";
2
+ /** Horizontal padding for a page shell, notch-aware. `base` is the design inset in px. */
3
+ export declare function pageInsetX(base: number): Pick<CSSProperties, "paddingLeft" | "paddingRight">;
@@ -0,0 +1,7 @@
1
+ import { type FilterRecord } from "./filter-evaluator";
2
+ import type { Entity, Screen } from "../types/schema";
3
+ export declare function resolveEntityVariantCode(entity: Entity, record: FilterRecord): string | undefined;
4
+ export declare function variantActionCodesForRecord(entity: Entity | undefined, record: FilterRecord): ReadonlySet<string> | undefined;
5
+ export declare function commonVariantActionCodes(entity: Entity | undefined, records: readonly FilterRecord[]): ReadonlySet<string> | undefined;
6
+ export declare function resolveScreenVariantCode(entity: Entity, screen: Screen, record: FilterRecord): string | undefined;
7
+ export declare function effectiveScreenForRecord(entity: Entity | undefined, screen: Screen | undefined, record: FilterRecord): Screen | undefined;
@@ -0,0 +1,44 @@
1
+ export type ViewportCategory = "phone" | "tablet" | "desktop";
2
+ export interface ResponsiveBreakpoints {
3
+ phoneMax: number;
4
+ tabletMax: number;
5
+ /**
6
+ * The height at or below which a viewport no wider than `tabletMax` is a
7
+ * phone held sideways. Required, never optional: a missing bound would
8
+ * silently restore the width-only rule, which is the defect it exists to
9
+ * remove.
10
+ */
11
+ landscapePhoneMaxHeight: number;
12
+ }
13
+ export interface ResponsiveViewport {
14
+ width: number;
15
+ height: number;
16
+ touch?: boolean;
17
+ }
18
+ export interface ResponsiveMode {
19
+ category: ViewportCategory;
20
+ width: number;
21
+ height: number;
22
+ isPhone: boolean;
23
+ isTablet: boolean;
24
+ isDesktop: boolean;
25
+ touch: boolean;
26
+ }
27
+ export declare const DEFAULT_RESPONSIVE_BREAKPOINTS: ResponsiveBreakpoints;
28
+ /**
29
+ * The device class, from BOTH viewport axes.
30
+ *
31
+ * A phone is a device, not a width. Read from width alone, the same phone is a
32
+ * phone upright and a tablet on its side - so rotating it swapped cards for a
33
+ * table, sections for tabs, and the compact header for the desktop one, all at
34
+ * once. The second clause is that device: no wider than a tablet AND short.
35
+ *
36
+ * Height is admitted only UNDER the tablet width ceiling, because a wide short
37
+ * window (a 1600x480 browser, a wide embed strip) is a desktop, and a height
38
+ * clause without the ceiling would reclassify it.
39
+ */
40
+ export declare function resolveViewportCategory(viewport: {
41
+ width: number;
42
+ height: number;
43
+ touch?: boolean;
44
+ }, breakpoints?: ResponsiveBreakpoints): ViewportCategory;