@almadar/std 16.187.0 → 16.189.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/behaviors/lolo/ui/core/.hand-authored.json +4 -4
- package/behaviors/lolo/ui/core/atoms/std-board.lolo +138 -4
- package/behaviors/lolo/ui/core/atoms/std-browse.lolo +148 -8
- package/behaviors/lolo/ui/core/atoms/std-calendar.lolo +161 -11
- package/behaviors/lolo/ui/core/atoms/std-event-log.lolo +255 -2
- package/behaviors/lolo/ui/core/atoms/std-gallery.lolo +148 -1
- package/behaviors/lolo/ui/core/atoms/std-list.lolo +193 -1
- package/behaviors/lolo/ui/core/atoms/std-record-detail.lolo +731 -0
- package/behaviors/lolo/ui/core/atoms/std-related.lolo +5 -1
- package/behaviors/lolo/ui/core/atoms/std-selection.lolo +182 -1
- package/behaviors/lolo/ui/core/atoms/std-tree.lolo +113 -3
- package/behaviors/lolo/ui/core/atoms/std-version-history.lolo +1 -1
- package/behaviors/lolo/ui/core/molecules/ui-document-details.lolo +80 -0
- package/behaviors/lolo/ui/core/molecules/ui-document-panel.lolo +213 -0
- package/behaviors/lolo/ui/core/molecules/{ui-rich-block-editor.lolo → ui-rich-text-editor.lolo} +25 -25
- package/behaviors/lolo/ui/game/atoms/std-area-fill.lolo +93 -0
- package/behaviors/lolo/ui/game/atoms/std-choice-gate.lolo +100 -0
- package/behaviors/lolo/ui/game/atoms/std-coef-pad.lolo +114 -0
- package/behaviors/lolo/ui/game/atoms/std-curve-fog.lolo +50 -0
- package/behaviors/lolo/ui/game/atoms/std-loop-lock.lolo +79 -0
- package/behaviors/lolo/ui/game/atoms/std-pad-lock.lolo +97 -0
- package/behaviors/lolo/ui/game/atoms/std-patrol-hazard.lolo +14 -7
- package/behaviors/lolo/ui/game/atoms/std-platformer-body.lolo +48 -5
- package/behaviors/lolo/ui/game/atoms/std-velocity-gate.lolo +101 -0
- package/behaviors/lolo/ui/game/atoms/std-zone-card.lolo +95 -0
- package/behaviors/lolo/ui/game/organisms/std-platformer-board-2d.lolo +9 -0
- package/behaviors/registry/infra/atoms/std-approval-gate.orb +16 -8
- package/behaviors/registry/infra/atoms/std-cache-aside.orb +62 -31
- package/behaviors/registry/infra/atoms/std-circuit-breaker.orb +32 -16
- package/behaviors/registry/infra/atoms/std-data-erasure.orb +16 -8
- package/behaviors/registry/infra/atoms/std-mod-queue.orb +16 -8
- package/behaviors/registry/infra/atoms/std-rate-limiter.orb +28 -14
- package/behaviors/registry/infra/organisms/std-status-lifecycle-control.orb +2 -1
- package/behaviors/registry/ml/organisms/std-escalating-decision.orb +10 -5
- package/behaviors/registry/ml/organisms/std-knowledge-tracing.orb +4 -2
- package/behaviors/registry/ui/core/atoms/std-billable-hour.orb +2 -1
- package/behaviors/registry/ui/core/atoms/std-board.orb +355 -2
- package/behaviors/registry/ui/core/atoms/std-browse.orb +304 -31
- package/behaviors/registry/ui/core/atoms/std-calendar.orb +393 -25
- package/behaviors/registry/ui/core/atoms/std-dashboard-grid-embedded.orb +2 -1
- package/behaviors/registry/ui/core/atoms/std-esign-flow.orb +4 -2
- package/behaviors/registry/ui/core/atoms/std-esign-request.orb +6 -3
- package/behaviors/registry/ui/core/atoms/std-event-log.orb +773 -0
- package/behaviors/registry/ui/core/atoms/std-export.orb +4 -2
- package/behaviors/registry/ui/core/atoms/std-gallery.orb +390 -0
- package/behaviors/registry/ui/core/atoms/std-import.orb +4 -2
- package/behaviors/registry/ui/core/atoms/std-list.orb +451 -0
- package/behaviors/registry/ui/core/atoms/std-record-detail.orb +3360 -0
- package/behaviors/registry/ui/core/atoms/std-related.orb +23 -1
- package/behaviors/registry/ui/core/atoms/std-selection.orb +436 -0
- package/behaviors/registry/ui/core/atoms/std-tree.orb +292 -1
- package/behaviors/registry/ui/core/atoms/std-version-history.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-document-details.orb +342 -0
- package/behaviors/registry/ui/core/molecules/ui-document-panel.orb +655 -0
- package/behaviors/registry/ui/core/molecules/{ui-rich-block-editor.orb → ui-rich-text-editor.orb} +84 -97
- package/behaviors/registry/ui/game/atoms/std-area-fill.orb +955 -0
- package/behaviors/registry/ui/game/atoms/std-choice-gate.orb +855 -0
- package/behaviors/registry/ui/game/atoms/std-coef-pad.orb +928 -0
- package/behaviors/registry/ui/game/atoms/std-curve-fog.orb +337 -0
- package/behaviors/registry/ui/game/atoms/std-fx-trail.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-gate-lock.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-lives.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-loop-lock.orb +785 -0
- package/behaviors/registry/ui/game/atoms/std-pad-lock.orb +933 -0
- package/behaviors/registry/ui/game/atoms/std-patrol-hazard.orb +190 -44
- package/behaviors/registry/ui/game/atoms/std-platformer-body.orb +1330 -653
- package/behaviors/registry/ui/game/atoms/std-velocity-gate.orb +1040 -0
- package/behaviors/registry/ui/game/atoms/std-zone-card.orb +642 -0
- package/behaviors/registry/ui/game/organisms/std-arcade-board-3d.orb +8 -4
- package/behaviors/registry/ui/game/organisms/std-crew-board-2d.orb +6 -3
- package/behaviors/registry/ui/game/organisms/std-dungeon-board-2d.orb +10 -5
- package/behaviors/registry/ui/game/organisms/std-market-board-3d.orb +8 -4
- package/behaviors/registry/ui/game/organisms/std-objective-board-3d.orb +8 -4
- package/behaviors/registry/ui/game/organisms/std-platformer-board-2d.orb +36 -1
- package/behaviors/registry/ui/game/organisms/std-survival-board-3d.orb +8 -4
- package/behaviors/registry/ui/game/organisms/std-tactics-board-2d.orb +12 -6
- package/behaviors/registry/ui/game/organisms/std-tactics-board-3d.orb +8 -4
- package/behaviors/registry/ui/game/organisms/std-worldmap-board-2d.orb +6 -3
- package/behaviors/registry/ui/learning/atoms/std-learn-slope-probe.orb +1 -1
- package/behaviors/registry/ui/marketing/atoms/std-marketing-article.orb +2 -1
- package/behaviors/registry/ui/marketing/atoms/std-marketing-footer.orb +2 -1
- package/behaviors/registry/ui/marketing/atoms/std-marketing-split.orb +2 -1
- package/behaviors/registry/ui/marketing/atoms/std-marketing-stats.orb +2 -1
- package/behaviors/registry/ui/marketing/atoms/std-marketing-steps.orb +2 -1
- package/behaviors/registry/ui/marketing/atoms/std-marketing-team.orb +2 -1
- package/dist/behaviors/exports-reader.js +10971 -6255
- package/dist/behaviors/functions/index.d.ts +1205 -256
- package/dist/behaviors/functions/index.js +10932 -6245
- package/dist/behaviors/index.d.ts +1 -1
- package/dist/behaviors/index.js +10972 -6256
- package/dist/behaviors/query.js +10971 -6255
- package/dist/behaviors-embeddings.hash.json +3 -3
- package/dist/behaviors-embeddings.json +485 -469
- package/dist/behaviors-registry.json +6125 -2940
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10972 -6256
- package/dist/knob-embeddings.hash.json +3 -3
- package/dist/knob-embeddings.json +1 -1
- package/dist/registry/factory-signatures.json +1 -1
- package/package.json +4 -4
- package/behaviors/lolo/ui/core/atoms/std-rich-editor.lolo +0 -790
- package/behaviors/registry/ui/core/atoms/std-rich-editor.orb +0 -2225
|
@@ -76,7 +76,7 @@ orbital RelatedItemOrbital {
|
|
|
76
76
|
gap: sm
|
|
77
77
|
type: stack
|
|
78
78
|
}, { type: divider }, {
|
|
79
|
-
entity: ?data
|
|
79
|
+
entity: (array/map ?data (fn row { id: @row.id, name: (object/get @row @config.labelField) }))
|
|
80
80
|
fields: []
|
|
81
81
|
look: @config.tableLook
|
|
82
82
|
renderItem: (fn item {
|
|
@@ -218,6 +218,10 @@ orbital RelatedItemOrbital {
|
|
|
218
218
|
@label "Section title"
|
|
219
219
|
@description "Heading shown above the related list."
|
|
220
220
|
@tier "presentation"
|
|
221
|
+
labelField : string = name
|
|
222
|
+
@label "Which field labels each related row?"
|
|
223
|
+
@description "Name of the field on the (rebound) related row rendered as the row label and carried as SELECT_RELATED's name — set it to `title` (etc.) whenever the bound entity labels rows differently. The rows are mapped through this at render time, because a trait-level `fields {}` rename is declaration-only on the runtime path and every populated row used to render a blank label."
|
|
224
|
+
@tier "presentation"
|
|
221
225
|
relationField : string = ""
|
|
222
226
|
@label "Relation field"
|
|
223
227
|
@description "RelatedItem field compared against SHOW_RELATED's key to scope the fetch to one parent document; empty renders the full unfiltered collection (default)."
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
app std-selection "1.0.0"
|
|
2
2
|
"std-selection as a Function"
|
|
3
|
+
type FilterSpec = { field : string!, label : string, options : [string] }
|
|
3
4
|
orbital SelectableItemOrbital {
|
|
4
5
|
type SelectableItemLoaded = Event { data : [SelectableItem] } "Fired when SelectableItem finishes loading; payload.data holds the list"
|
|
5
6
|
|
|
@@ -46,7 +47,37 @@ orbital SelectableItemOrbital {
|
|
|
46
47
|
direction: horizontal
|
|
47
48
|
gap: sm
|
|
48
49
|
type: stack
|
|
49
|
-
},
|
|
50
|
+
}, (if @config.bodySearch {
|
|
51
|
+
children: [{
|
|
52
|
+
className: "w-full max-w-md"
|
|
53
|
+
clearable: true
|
|
54
|
+
event: REFETCH_QUERY
|
|
55
|
+
placeholder: @config.searchPlaceholder
|
|
56
|
+
type: search-input
|
|
57
|
+
}]
|
|
58
|
+
direction: horizontal
|
|
59
|
+
gap: sm
|
|
60
|
+
type: stack
|
|
61
|
+
} {
|
|
62
|
+
children: []
|
|
63
|
+
gap: none
|
|
64
|
+
type: stack
|
|
65
|
+
}), (if [">", (array/len @config.filters), 0] {
|
|
66
|
+
children: [{
|
|
67
|
+
entity: SelectableItem
|
|
68
|
+
event: REFETCH_FILTER
|
|
69
|
+
filters: @config.filters
|
|
70
|
+
look: @config.filterBarLook
|
|
71
|
+
type: filter-group
|
|
72
|
+
}]
|
|
73
|
+
direction: horizontal
|
|
74
|
+
gap: sm
|
|
75
|
+
type: stack
|
|
76
|
+
} {
|
|
77
|
+
children: []
|
|
78
|
+
gap: none
|
|
79
|
+
type: stack
|
|
80
|
+
}), { type: divider }, {
|
|
50
81
|
color: muted
|
|
51
82
|
content: "Choose a selectableitem to continue."
|
|
52
83
|
type: typography
|
|
@@ -61,6 +92,7 @@ orbital SelectableItemOrbital {
|
|
|
61
92
|
label: Select
|
|
62
93
|
}]
|
|
63
94
|
look: @config.tableLook
|
|
95
|
+
pageSize: @config.displayPageSize
|
|
64
96
|
renderItem: (fn item {
|
|
65
97
|
align: center
|
|
66
98
|
children: [{ label: @item.name, type: checkbox }]
|
|
@@ -105,6 +137,106 @@ orbital SelectableItemOrbital {
|
|
|
105
137
|
}
|
|
106
138
|
|
|
107
139
|
state idle {
|
|
140
|
+
;; REFETCH_* stays in `idle` and DOES NOT replace the pick-list with a
|
|
141
|
+
;; spinner — same reasoning as std-browse's REFETCH_* arms: a skeleton
|
|
142
|
+
;; on refetch unmounts the list and flickers every keystroke. The fetch
|
|
143
|
+
;; fires in the background; the SelectableItemLoaded arm below
|
|
144
|
+
;; re-renders in place once it lands.
|
|
145
|
+
REFETCH_QUERY -> idle
|
|
146
|
+
(fetch SelectableItem {
|
|
147
|
+
emit: { failure: SelectableItemLoadFailed, success: SelectableItemLoaded }
|
|
148
|
+
filter: (or ["=", ?searchTerm, ""] (str/includes (object/get @entity name) ?searchTerm))
|
|
149
|
+
})
|
|
150
|
+
REFETCH_FILTER -> idle
|
|
151
|
+
(fetch SelectableItem {
|
|
152
|
+
emit: { failure: SelectableItemLoadFailed, success: SelectableItemLoaded }
|
|
153
|
+
filter: (or ["=", ?value, ""] ["=", (object/get @entity ?field), ?value])
|
|
154
|
+
})
|
|
155
|
+
;; No filter carried over on REFETCH_PAGE, mirroring std-browse exactly.
|
|
156
|
+
;; Paging is safe here: this atom's selection is a single transient id
|
|
157
|
+
;; carried only in the SELECT/CONFIRM_SELECTION payload (`?id`), never
|
|
158
|
+
;; accumulated into a persisted @entity array, so turning a page cannot
|
|
159
|
+
;; strand an "already selected" item — there is no multi-item selection
|
|
160
|
+
;; state to strand. A future multi-select variant that DOES accumulate
|
|
161
|
+
;; picks into an @entity field would need to carry that array across
|
|
162
|
+
;; REFETCH_PAGE explicitly; this single-pick atom does not need to.
|
|
163
|
+
REFETCH_PAGE -> idle
|
|
164
|
+
(fetch SelectableItem {
|
|
165
|
+
emit: { failure: SelectableItemLoadFailed, success: SelectableItemLoaded }
|
|
166
|
+
limit: @config.pageSize
|
|
167
|
+
offset: ["*", ["-", ?page, 1], @config.pageSize]
|
|
168
|
+
})
|
|
169
|
+
SelectableItemLoaded -> idle
|
|
170
|
+
(render-ui main {
|
|
171
|
+
children: [{
|
|
172
|
+
align: center
|
|
173
|
+
children: [{ name: check-square, type: icon }, {
|
|
174
|
+
content: SelectableItems
|
|
175
|
+
type: typography
|
|
176
|
+
variant: h2
|
|
177
|
+
}]
|
|
178
|
+
direction: horizontal
|
|
179
|
+
gap: sm
|
|
180
|
+
type: stack
|
|
181
|
+
}, (if @config.bodySearch {
|
|
182
|
+
children: [{
|
|
183
|
+
className: "w-full max-w-md"
|
|
184
|
+
clearable: true
|
|
185
|
+
event: REFETCH_QUERY
|
|
186
|
+
placeholder: @config.searchPlaceholder
|
|
187
|
+
type: search-input
|
|
188
|
+
}]
|
|
189
|
+
direction: horizontal
|
|
190
|
+
gap: sm
|
|
191
|
+
type: stack
|
|
192
|
+
} {
|
|
193
|
+
children: []
|
|
194
|
+
gap: none
|
|
195
|
+
type: stack
|
|
196
|
+
}), (if [">", (array/len @config.filters), 0] {
|
|
197
|
+
children: [{
|
|
198
|
+
entity: SelectableItem
|
|
199
|
+
event: REFETCH_FILTER
|
|
200
|
+
filters: @config.filters
|
|
201
|
+
look: @config.filterBarLook
|
|
202
|
+
type: filter-group
|
|
203
|
+
}]
|
|
204
|
+
direction: horizontal
|
|
205
|
+
gap: sm
|
|
206
|
+
type: stack
|
|
207
|
+
} {
|
|
208
|
+
children: []
|
|
209
|
+
gap: none
|
|
210
|
+
type: stack
|
|
211
|
+
}), { type: divider }, {
|
|
212
|
+
color: muted
|
|
213
|
+
content: "Choose a selectableitem to continue."
|
|
214
|
+
type: typography
|
|
215
|
+
variant: caption
|
|
216
|
+
}, {
|
|
217
|
+
className: "transition-shadow hover:shadow-md cursor-pointer"
|
|
218
|
+
entity: ?data
|
|
219
|
+
fields: []
|
|
220
|
+
itemActions: [{
|
|
221
|
+
event: SELECT
|
|
222
|
+
icon: check
|
|
223
|
+
label: Select
|
|
224
|
+
}]
|
|
225
|
+
look: @config.tableLook
|
|
226
|
+
pageSize: @config.displayPageSize
|
|
227
|
+
renderItem: (fn item {
|
|
228
|
+
align: center
|
|
229
|
+
children: [{ label: @item.name, type: checkbox }]
|
|
230
|
+
direction: horizontal
|
|
231
|
+
gap: sm
|
|
232
|
+
type: stack
|
|
233
|
+
})
|
|
234
|
+
type: data-grid
|
|
235
|
+
}]
|
|
236
|
+
direction: vertical
|
|
237
|
+
gap: lg
|
|
238
|
+
type: stack
|
|
239
|
+
})
|
|
108
240
|
SELECT -> selecting
|
|
109
241
|
(render-ui main {
|
|
110
242
|
children: [{
|
|
@@ -269,6 +401,25 @@ orbital SelectableItemOrbital {
|
|
|
269
401
|
@description "Indicates a selectable item failed to load."
|
|
270
402
|
@synonyms "error, failure, problem, load error"
|
|
271
403
|
@tier "internal"
|
|
404
|
+
REFETCH_QUERY {
|
|
405
|
+
searchTerm : string!
|
|
406
|
+
}
|
|
407
|
+
@description "Triggers a pick-list refresh based on the current search term."
|
|
408
|
+
@synonyms "refresh, reload, update, re-query, search"
|
|
409
|
+
@tier "domain"
|
|
410
|
+
REFETCH_FILTER {
|
|
411
|
+
field : string!
|
|
412
|
+
value : string!
|
|
413
|
+
}
|
|
414
|
+
@description "Triggers a pick-list refresh based on current filter criteria."
|
|
415
|
+
@synonyms "refresh, filter, update, reload"
|
|
416
|
+
@tier "domain"
|
|
417
|
+
REFETCH_PAGE {
|
|
418
|
+
page : number!
|
|
419
|
+
}
|
|
420
|
+
@description "Triggers a pick-list page refresh."
|
|
421
|
+
@synonyms "reload, refresh, update, paginate"
|
|
422
|
+
@tier "domain"
|
|
272
423
|
}
|
|
273
424
|
|
|
274
425
|
config {
|
|
@@ -276,6 +427,36 @@ orbital SelectableItemOrbital {
|
|
|
276
427
|
@label "Table look"
|
|
277
428
|
@description "Layer 2 visual treatment for the data table rendered by this atom."
|
|
278
429
|
@tier "presentation"
|
|
430
|
+
bodySearch : boolean = false
|
|
431
|
+
@label "Show the pick-list's own search box?"
|
|
432
|
+
@description "Embeds a search box above the pick-list. Set true only when the page has no other search affordance (e.g. no page-level std-search), so the surface shows one search box instead of two. False is the default — this atom has never had a search box (0 consumers today)."
|
|
433
|
+
@synonyms "inline search, list search, built-in search, show search"
|
|
434
|
+
@tier "presentation"
|
|
435
|
+
searchPlaceholder : string = "Search…"
|
|
436
|
+
@label "Search box placeholder text"
|
|
437
|
+
@description "Hint text inside the pick-list search box."
|
|
438
|
+
@synonyms "search hint, placeholder, search box text"
|
|
439
|
+
@tier "presentation"
|
|
440
|
+
filters : [FilterSpec] = []
|
|
441
|
+
@label "Which filters should appear above the pick-list?"
|
|
442
|
+
@description "Dropdown filter facets by field, rendered as an embedded filter bar above the rows; each selection fires REFETCH_FILTER on this trait. Empty (the default) = no filter bar, the right setting whenever the page already composes std-filter beside this list and routes XFilter.FILTER -> REFETCH_FILTER — that is the wired owner and remains the primary path. Use this knob only for a standalone pick-list with no page-level filter affordance."
|
|
443
|
+
@synonyms "filter bar, faceted filters, field filters, dropdowns"
|
|
444
|
+
@tier "presentation"
|
|
445
|
+
filterBarLook : "toolbar" | "chips" | "pills" | "popover-trigger" | "inline-column-header" = toolbar
|
|
446
|
+
@label "Filter bar look"
|
|
447
|
+
@description "Visual treatment for the embedded filter bar, mirroring std-filter's own enum. Only applies when `filters` is non-empty."
|
|
448
|
+
@synonyms "filter bar style, facet style, chips, pills"
|
|
449
|
+
@tier "presentation"
|
|
450
|
+
pageSize : number = 20
|
|
451
|
+
@label "How many candidates per page when paging?"
|
|
452
|
+
@description "Records fetched from the server per REFETCH_PAGE request. The initial load and search/filter refetches remain unpaginated (load every candidate) unless a consumer wires REFETCH_PAGE, so the default pick-list surface is unchanged. Safe to page: this atom's selection is a single transient id (never an accumulated array), so no already-picked item can be stranded on another page."
|
|
453
|
+
@synonyms "fetch limit, records per page, page limit"
|
|
454
|
+
@tier "presentation"
|
|
455
|
+
displayPageSize : number = 20
|
|
456
|
+
@label "How many candidates to show at once?"
|
|
457
|
+
@description "Rows visible per page before the data-grid's own pagination control appears — 20 matches the pick-list density sweet spot (Miller's law, 10-25 rows)."
|
|
458
|
+
@synonyms "visible rows, items per page, display limit, show per page"
|
|
459
|
+
@tier "presentation"
|
|
279
460
|
}
|
|
280
461
|
}
|
|
281
462
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
app std-tree "1.0.0"
|
|
2
|
-
"std-tree — generic hierarchical node browser. Fetches a flat TreeNode collection and renders it through file-tree's flat `items` mode (parentId-nested at render time by the component, not the .lolo); OPEN_NODE is the external handoff for a selected node's id. Rebindable: pass `fields` at the call site to retarget it at any parent-pointer entity (categories, org units, comment threads)."
|
|
2
|
+
"std-tree — generic hierarchical node browser. Fetches a flat TreeNode collection and renders it through file-tree's flat `items` mode (parentId-nested at render time by the component, not the .lolo); OPEN_NODE is the external handoff for a selected node's id. Rebindable: pass `fields` at the call site to retarget it at any parent-pointer entity (categories, org units, comment threads). Search/filter are wired (REFETCH_QUERY/REFETCH_FILTER re-fetch the flat node set server-side); pagination is deliberately NOT offered — a hierarchy is not a paged list, and paging a flat node set would sever children from parents that fell on another page."
|
|
3
|
+
type FilterSpec = { field : string!, label : string, options : [string] }
|
|
3
4
|
orbital TreeNodeOrbital {
|
|
4
5
|
type TreeNodeLoaded = Event { data : [TreeNode] } "Fired when the tree node collection finishes loading"
|
|
5
6
|
|
|
@@ -51,7 +52,37 @@ orbital TreeNodeOrbital {
|
|
|
51
52
|
direction: horizontal
|
|
52
53
|
gap: sm
|
|
53
54
|
type: stack
|
|
54
|
-
}, { type: divider }, {
|
|
55
|
+
}, { type: divider }, (if @config.bodySearch {
|
|
56
|
+
children: [{
|
|
57
|
+
className: "w-full max-w-md"
|
|
58
|
+
clearable: true
|
|
59
|
+
event: REFETCH_QUERY
|
|
60
|
+
placeholder: @config.searchPlaceholder
|
|
61
|
+
type: search-input
|
|
62
|
+
}]
|
|
63
|
+
direction: horizontal
|
|
64
|
+
gap: sm
|
|
65
|
+
type: stack
|
|
66
|
+
} {
|
|
67
|
+
children: []
|
|
68
|
+
gap: none
|
|
69
|
+
type: stack
|
|
70
|
+
}), (if [">", (array/len @config.filters), 0] {
|
|
71
|
+
children: [{
|
|
72
|
+
entity: TreeNode
|
|
73
|
+
event: REFETCH_FILTER
|
|
74
|
+
filters: @config.filters
|
|
75
|
+
look: @config.filterBarLook
|
|
76
|
+
type: filter-group
|
|
77
|
+
}]
|
|
78
|
+
direction: horizontal
|
|
79
|
+
gap: sm
|
|
80
|
+
type: stack
|
|
81
|
+
} {
|
|
82
|
+
children: []
|
|
83
|
+
gap: none
|
|
84
|
+
type: stack
|
|
85
|
+
}), {
|
|
55
86
|
items: (array/map ?data (fn row {
|
|
56
87
|
icon: @row.icon
|
|
57
88
|
id: @row.id
|
|
@@ -113,6 +144,22 @@ orbital TreeNodeOrbital {
|
|
|
113
144
|
gap: md
|
|
114
145
|
type: stack
|
|
115
146
|
})
|
|
147
|
+
;; REFETCH_* stays in `browsing` and DOES NOT replace the tree with a
|
|
148
|
+
;; spinner — search-as-you-type would otherwise unmount file-tree every
|
|
149
|
+
;; keystroke and flicker. The fetch fires in the background; when
|
|
150
|
+
;; TreeNodeLoaded arrives (handler below) React reconciles the tree in
|
|
151
|
+
;; place. No REFETCH_PAGE: a hierarchy is not a paged list — paging the
|
|
152
|
+
;; flat node set would sever children from parents on another page.
|
|
153
|
+
REFETCH_QUERY -> browsing
|
|
154
|
+
(fetch TreeNode {
|
|
155
|
+
emit: { failure: TreeNodeLoadFailed, success: TreeNodeLoaded }
|
|
156
|
+
filter: (or ["=", ?searchTerm, ""] (str/includes (object/get @entity name) ?searchTerm))
|
|
157
|
+
})
|
|
158
|
+
REFETCH_FILTER -> browsing
|
|
159
|
+
(fetch TreeNode {
|
|
160
|
+
emit: { failure: TreeNodeLoadFailed, success: TreeNodeLoaded }
|
|
161
|
+
filter: (or ["=", ?value, ""] ["=", (object/get @entity ?field), ?value])
|
|
162
|
+
})
|
|
116
163
|
OPEN_NODE -> browsing
|
|
117
164
|
(set @entity.id ?id)
|
|
118
165
|
TreeNodeLoaded -> browsing
|
|
@@ -132,7 +179,37 @@ orbital TreeNodeOrbital {
|
|
|
132
179
|
direction: horizontal
|
|
133
180
|
gap: sm
|
|
134
181
|
type: stack
|
|
135
|
-
}, { type: divider }, {
|
|
182
|
+
}, { type: divider }, (if @config.bodySearch {
|
|
183
|
+
children: [{
|
|
184
|
+
className: "w-full max-w-md"
|
|
185
|
+
clearable: true
|
|
186
|
+
event: REFETCH_QUERY
|
|
187
|
+
placeholder: @config.searchPlaceholder
|
|
188
|
+
type: search-input
|
|
189
|
+
}]
|
|
190
|
+
direction: horizontal
|
|
191
|
+
gap: sm
|
|
192
|
+
type: stack
|
|
193
|
+
} {
|
|
194
|
+
children: []
|
|
195
|
+
gap: none
|
|
196
|
+
type: stack
|
|
197
|
+
}), (if [">", (array/len @config.filters), 0] {
|
|
198
|
+
children: [{
|
|
199
|
+
entity: TreeNode
|
|
200
|
+
event: REFETCH_FILTER
|
|
201
|
+
filters: @config.filters
|
|
202
|
+
look: @config.filterBarLook
|
|
203
|
+
type: filter-group
|
|
204
|
+
}]
|
|
205
|
+
direction: horizontal
|
|
206
|
+
gap: sm
|
|
207
|
+
type: stack
|
|
208
|
+
} {
|
|
209
|
+
children: []
|
|
210
|
+
gap: none
|
|
211
|
+
type: stack
|
|
212
|
+
}), {
|
|
136
213
|
items: (array/map ?data (fn row {
|
|
137
214
|
icon: @row.icon
|
|
138
215
|
id: @row.id
|
|
@@ -214,6 +291,19 @@ orbital TreeNodeOrbital {
|
|
|
214
291
|
}
|
|
215
292
|
|
|
216
293
|
listens {
|
|
294
|
+
REFETCH_QUERY {
|
|
295
|
+
searchTerm : string!
|
|
296
|
+
}
|
|
297
|
+
@description "Triggers a tree refresh based on the current search query."
|
|
298
|
+
@synonyms "refresh, reload, update, re-query"
|
|
299
|
+
@tier "domain"
|
|
300
|
+
REFETCH_FILTER {
|
|
301
|
+
field : string!
|
|
302
|
+
value : string!
|
|
303
|
+
}
|
|
304
|
+
@description "Triggers a tree refresh based on current filter criteria."
|
|
305
|
+
@synonyms "refresh, filter, update, reload"
|
|
306
|
+
@tier "domain"
|
|
217
307
|
OPEN_NODE {
|
|
218
308
|
id : string!
|
|
219
309
|
}
|
|
@@ -240,6 +330,26 @@ orbital TreeNodeOrbital {
|
|
|
240
330
|
@label "Section title"
|
|
241
331
|
@description "Heading shown above the tree"
|
|
242
332
|
@tier "presentation"
|
|
333
|
+
bodySearch : boolean = false
|
|
334
|
+
@label "Show the tree's own search box?"
|
|
335
|
+
@description "Embeds a search box above the tree that re-fetches the flat node set server-side. Set false (the default) when the page already provides a search affordance (a toolbar Search molecule), so the surface shows one search box instead of two."
|
|
336
|
+
@synonyms "inline search, list search, built-in search, show search, duplicate search"
|
|
337
|
+
@tier "presentation"
|
|
338
|
+
searchPlaceholder : string = "Search…"
|
|
339
|
+
@label "Search box placeholder text"
|
|
340
|
+
@description "Hint text inside the tree search box (e.g. 'Search nodes…')."
|
|
341
|
+
@synonyms "search hint, placeholder, search box text, search label"
|
|
342
|
+
@tier "presentation"
|
|
343
|
+
filters : [FilterSpec] = []
|
|
344
|
+
@label "Which filters should appear above the tree?"
|
|
345
|
+
@description "Dropdown filter facets by field, rendered as an embedded filter bar above the tree; each selection fires REFETCH_FILTER on this trait, re-fetching the flat node set. Empty (the default) = no filter bar, which is the right setting whenever the page already composes std-filter beside this tree and routes `XFilter.FILTER -> REFETCH_FILTER` — that is the wired owner and remains the primary path."
|
|
346
|
+
@synonyms "filter bar, faceted filters, field filters, dropdowns"
|
|
347
|
+
@tier "presentation"
|
|
348
|
+
filterBarLook : "toolbar" | "chips" | "pills" | "popover-trigger" | "inline-column-header" = toolbar
|
|
349
|
+
@label "Filter bar look"
|
|
350
|
+
@description "Visual treatment for the embedded filter bar, mirroring std-filter's own enum. Only applies when `filters` is non-empty."
|
|
351
|
+
@synonyms "filter bar style, facet style, chips, pills"
|
|
352
|
+
@tier "presentation"
|
|
243
353
|
}
|
|
244
354
|
}
|
|
245
355
|
|
|
@@ -16,7 +16,7 @@ orbital RevisionOrbital {
|
|
|
16
16
|
versionNumber : number! @description "A sequential identifier representing the revision's order." @synonyms "sequence, order, iteration"
|
|
17
17
|
authorId : string @description "Unique identifier for the user who made the change." @synonyms "user identifier, creator, contributor"
|
|
18
18
|
authorName : string @description "The name of the user who made the change." @synonyms "user, contributor, owner"
|
|
19
|
-
content : string @description "The
|
|
19
|
+
content : string @description "The snapshotted body of the revision — plain text or the rich-text HTML a document-look record carries. Rollback hands the whole row back to the host, which restores content onto the source document." @synonyms "text, body, data, value"
|
|
20
20
|
summary : string @description "A brief explanation of the revision's changes." @synonyms "description, note, comment, explanation"
|
|
21
21
|
searchTerm : string @description "The current search query the user submitted." @synonyms "query, term, q" = ""
|
|
22
22
|
createdAt : string
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
app ui-document-details "1.0.0"
|
|
2
|
+
"DocumentDetails — the document's metadata as a compact settings card for the rail beside a DocumentPanel, each property committing in place. — UI factory (1:1 with the @almadar/ui document-details pattern)."
|
|
3
|
+
;; @capabilities "document settings, page details, post settings sidebar, metadata panel, document properties, publish settings"
|
|
4
|
+
orbital DocumentDetailsOrbital {
|
|
5
|
+
type DocumentDetailsLoaded = Event { data : [DocumentDetailsItem] } "DocumentDetails rows finished loading; payload.data holds the collection"
|
|
6
|
+
type DocumentDetailsFieldsItem = {
|
|
7
|
+
name : string
|
|
8
|
+
key : string
|
|
9
|
+
label : string
|
|
10
|
+
header : string
|
|
11
|
+
icon : icon
|
|
12
|
+
kind : "text" | "boolean" | "select" | "readonly"
|
|
13
|
+
options : [string]
|
|
14
|
+
format : "date" | "currency" | "number" | "boolean" | "percent"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
entity DocumentDetailsItem [runtime] {
|
|
18
|
+
id : string!
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
trait DocumentDetailsRender -> @rebindable DocumentDetailsItem [interaction, instance] {
|
|
22
|
+
initial: idle
|
|
23
|
+
|
|
24
|
+
state idle {
|
|
25
|
+
INIT -> idle
|
|
26
|
+
(fetch DocumentDetailsItem { emit: { success: DocumentDetailsLoaded } })
|
|
27
|
+
(render-ui main {
|
|
28
|
+
entity: @entity
|
|
29
|
+
fields: @config.fields
|
|
30
|
+
metaCommitEvent: @config.metaCommitEvent
|
|
31
|
+
title: @config.title
|
|
32
|
+
className: @config.className
|
|
33
|
+
type: document-details
|
|
34
|
+
})
|
|
35
|
+
DocumentDetailsLoaded -> idle
|
|
36
|
+
(render-ui main {
|
|
37
|
+
entity: @payload.data
|
|
38
|
+
fields: @config.fields
|
|
39
|
+
metaCommitEvent: @config.metaCommitEvent
|
|
40
|
+
title: @config.title
|
|
41
|
+
className: @config.className
|
|
42
|
+
type: document-details
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
emits {
|
|
47
|
+
@config.metaCommitEvent -> external {
|
|
48
|
+
id : string!
|
|
49
|
+
patch : object!
|
|
50
|
+
}
|
|
51
|
+
@description "Emitted when a property commits: { id, patch } — patch carries the id plus the one changed field, ready for a partial persist update."
|
|
52
|
+
@tier "essential"
|
|
53
|
+
DocumentDetailsLoaded
|
|
54
|
+
@description "DocumentDetails rows finished loading; payload.data holds the collection."
|
|
55
|
+
@synonyms "loaded, fetched, retrieved"
|
|
56
|
+
@tier "essential"
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
config {
|
|
60
|
+
fields : [DocumentDetailsFieldsItem] = []
|
|
61
|
+
@label "Fields"
|
|
62
|
+
@description "The properties shown; empty renders nothing."
|
|
63
|
+
@tier "presentation"
|
|
64
|
+
metaCommitEvent : string = "META_COMMIT"
|
|
65
|
+
@label "Meta Commit Event"
|
|
66
|
+
@description "Emitted when a property commits: { id, patch } — patch carries the id plus the one changed field, ready for a partial persist update."
|
|
67
|
+
@tier "presentation"
|
|
68
|
+
title : string
|
|
69
|
+
@label "Title"
|
|
70
|
+
@description "Card heading (defaults to the localized 'Details')"
|
|
71
|
+
@tier "presentation"
|
|
72
|
+
className : string
|
|
73
|
+
@label "Class Name"
|
|
74
|
+
@description "className prop"
|
|
75
|
+
@tier "presentation"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
page "/document-details" as DocumentDetailsPage -> DocumentDetailsRender
|
|
80
|
+
}
|