@almadar/std 16.191.0 → 16.193.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/infra/atoms/std-approval-gate.lolo +184 -18
- package/behaviors/lolo/infra/atoms/std-status-lifecycle.lolo +16 -3
- package/behaviors/lolo/ui/core/atoms/std-app-layout.lolo +6 -0
- package/behaviors/lolo/ui/core/atoms/std-billable-hour.lolo +1 -0
- package/behaviors/lolo/ui/core/atoms/std-browse.lolo +3 -0
- package/behaviors/lolo/ui/core/atoms/std-image-upload-multi.lolo +37 -4
- package/behaviors/lolo/ui/core/atoms/std-record-detail.lolo +37 -0
- package/behaviors/lolo/ui/core/atoms/std-tag-strip.lolo +314 -0
- package/behaviors/lolo/ui/core/atoms/std-tag-taxonomy.lolo +195 -13
- package/behaviors/lolo/ui/core/atoms/std-tree.lolo +104 -12
- package/behaviors/lolo/ui/core/atoms/std-version-history.lolo +3 -1
- package/behaviors/lolo/ui/core/molecules/ui-calendar-grid.lolo +25 -1
- package/behaviors/lolo/ui/core/molecules/ui-data-grid.lolo +37 -1
- package/behaviors/lolo/ui/core/molecules/ui-data-list.lolo +46 -1
- package/behaviors/lolo/ui/core/molecules/ui-document-details.lolo +30 -2
- package/behaviors/lolo/ui/core/molecules/ui-document-panel.lolo +14 -0
- package/behaviors/lolo/ui/core/molecules/ui-file-tree.lolo +25 -0
- package/behaviors/lolo/ui/core/molecules/ui-positioned-canvas.lolo +19 -1
- package/behaviors/lolo/ui/core/molecules/ui-reply-tree.lolo +21 -1
- package/behaviors/lolo/ui/core/molecules/ui-sortable-list.lolo +15 -1
- package/behaviors/lolo/ui/core/molecules/ui-table-view.lolo +36 -1
- package/behaviors/lolo/ui/core/organisms/ui-detail-panel.lolo +41 -1
- package/behaviors/lolo/ui/core/organisms/ui-entity-cards.lolo +34 -1
- package/behaviors/lolo/ui/core/organisms/ui-entity-list.lolo +30 -1
- package/behaviors/lolo/ui/core/organisms/ui-entity-table.lolo +36 -1
- package/behaviors/lolo/ui/core/organisms/ui-form-section.lolo +39 -1
- package/behaviors/lolo/ui/core/organisms/ui-form.lolo +39 -1
- package/behaviors/lolo/ui/core/organisms/ui-master-detail.lolo +24 -1
- package/behaviors/lolo/ui/core/organisms/ui-media-gallery.lolo +30 -1
- package/behaviors/lolo/ui/core/organisms/ui-stat-card.lolo +37 -1
- package/behaviors/lolo/ui/core/organisms/ui-timeline.lolo +18 -1
- package/behaviors/lolo/ui/core/templates/ui-counter-template.lolo +21 -1
- package/behaviors/lolo/ui/core/templates/ui-dashboard-layout.lolo +5 -0
- package/behaviors/lolo/ui/core/templates/ui-generic-app-template.lolo +16 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-book-chapter-view.lolo +12 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-book-table-of-contents.lolo +13 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-book-viewer.lolo +23 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-case-study-organism.lolo +23 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-feature-grid-organism.lolo +24 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-hero-organism.lolo +22 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-pricing-organism.lolo +23 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-showcase-organism.lolo +24 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-stats-organism.lolo +22 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-step-flow-organism.lolo +25 -1
- package/behaviors/lolo/ui/marketing/organisms/ui-team-organism.lolo +23 -1
- package/behaviors/lolo/ui/marketing/templates/ui-about-page-template.lolo +11 -1
- package/behaviors/lolo/ui/marketing/templates/ui-feature-detail-page-template.lolo +11 -1
- package/behaviors/lolo/ui/marketing/templates/ui-landing-page-template.lolo +13 -1
- package/behaviors/lolo/ui/marketing/templates/ui-pricing-page-template.lolo +11 -1
- package/behaviors/registry/infra/atoms/std-approval-gate.orb +717 -45
- package/behaviors/registry/infra/atoms/std-status-lifecycle.orb +85 -10
- package/behaviors/registry/ui/core/atoms/std-app-layout.orb +8 -0
- package/behaviors/registry/ui/core/atoms/std-billable-hour.orb +5 -2
- package/behaviors/registry/ui/core/atoms/std-browse.orb +12 -0
- package/behaviors/registry/ui/core/atoms/std-image-upload-multi.orb +129 -7
- package/behaviors/registry/ui/core/atoms/std-record-detail.orb +316 -0
- package/behaviors/registry/ui/core/atoms/std-tag-strip.orb +1360 -0
- package/behaviors/registry/ui/core/atoms/std-tag-taxonomy.orb +564 -10
- package/behaviors/registry/ui/core/atoms/std-tree.orb +427 -66
- package/behaviors/registry/ui/core/atoms/std-version-history.orb +5 -1
- package/behaviors/registry/ui/core/molecules/ui-calendar-grid.orb +43 -0
- package/behaviors/registry/ui/core/molecules/ui-data-grid.orb +55 -0
- package/behaviors/registry/ui/core/molecules/ui-data-list.orb +64 -0
- package/behaviors/registry/ui/core/molecules/ui-document-details.orb +106 -1
- package/behaviors/registry/ui/core/molecules/ui-document-panel.orb +18 -0
- package/behaviors/registry/ui/core/molecules/ui-file-tree.orb +41 -0
- package/behaviors/registry/ui/core/molecules/ui-positioned-canvas.orb +37 -0
- package/behaviors/registry/ui/core/molecules/ui-reply-tree.orb +39 -0
- package/behaviors/registry/ui/core/molecules/ui-sortable-list.orb +45 -0
- package/behaviors/registry/ui/core/molecules/ui-table-view.orb +54 -0
- package/behaviors/registry/ui/core/organisms/ui-detail-panel.orb +59 -0
- package/behaviors/registry/ui/core/organisms/ui-entity-cards.orb +52 -0
- package/behaviors/registry/ui/core/organisms/ui-entity-list.orb +48 -0
- package/behaviors/registry/ui/core/organisms/ui-entity-table.orb +54 -0
- package/behaviors/registry/ui/core/organisms/ui-form-section.orb +57 -0
- package/behaviors/registry/ui/core/organisms/ui-form.orb +57 -0
- package/behaviors/registry/ui/core/organisms/ui-master-detail.orb +42 -0
- package/behaviors/registry/ui/core/organisms/ui-media-gallery.orb +48 -0
- package/behaviors/registry/ui/core/organisms/ui-stat-card.orb +55 -0
- package/behaviors/registry/ui/core/organisms/ui-timeline.orb +36 -0
- package/behaviors/registry/ui/core/templates/ui-counter-template.orb +39 -0
- package/behaviors/registry/ui/core/templates/ui-dashboard-layout.orb +7 -0
- package/behaviors/registry/ui/core/templates/ui-generic-app-template.orb +34 -0
- package/behaviors/registry/ui/marketing/organisms/ui-book-chapter-view.orb +30 -0
- package/behaviors/registry/ui/marketing/organisms/ui-book-table-of-contents.orb +31 -0
- package/behaviors/registry/ui/marketing/organisms/ui-book-viewer.orb +41 -0
- package/behaviors/registry/ui/marketing/organisms/ui-case-study-organism.orb +41 -0
- package/behaviors/registry/ui/marketing/organisms/ui-feature-grid-organism.orb +42 -0
- package/behaviors/registry/ui/marketing/organisms/ui-hero-organism.orb +40 -0
- package/behaviors/registry/ui/marketing/organisms/ui-pricing-organism.orb +41 -0
- package/behaviors/registry/ui/marketing/organisms/ui-showcase-organism.orb +42 -0
- package/behaviors/registry/ui/marketing/organisms/ui-stats-organism.orb +40 -0
- package/behaviors/registry/ui/marketing/organisms/ui-step-flow-organism.orb +43 -0
- package/behaviors/registry/ui/marketing/organisms/ui-team-organism.orb +41 -0
- package/behaviors/registry/ui/marketing/templates/ui-about-page-template.orb +29 -0
- package/behaviors/registry/ui/marketing/templates/ui-feature-detail-page-template.orb +29 -0
- package/behaviors/registry/ui/marketing/templates/ui-landing-page-template.orb +31 -0
- package/behaviors/registry/ui/marketing/templates/ui-pricing-page-template.orb +29 -0
- package/dist/behaviors/exports-reader.js +4884 -1967
- package/dist/behaviors/functions/index.d.ts +293 -13
- package/dist/behaviors/functions/index.js +4880 -1968
- package/dist/behaviors/index.d.ts +1 -1
- package/dist/behaviors/index.js +4885 -1968
- package/dist/behaviors/query.js +4884 -1967
- package/dist/behaviors-embeddings.hash.json +3 -3
- package/dist/behaviors-embeddings.json +21 -13
- package/dist/behaviors-registry.json +685 -60
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4885 -1968
- 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 +2 -2
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
app std-tag-strip "1.0.0"
|
|
2
|
+
"std-tag-strip — inline tag editing ON the document surface: the record's tags render as removable chips with a type-to-add input (a typed name that matches an existing tag attaches it; an unknown name is created in the shared taxonomy first), plus one-click chips for every existing tag not yet attached. Emits TAGS_CHANGED { id, tagIds } — the host organism routes it into its persistor's update; the document's refetch re-scopes the strip. Binds any record carrying a tagIds relation array; the tag store is the shared `tags` collection (std-tag-taxonomy's)."
|
|
3
|
+
;; @capabilities "inline tags, tag chips on a document, add tag from taxonomy, create tag by typing, remove tag chip, tag editing in place"
|
|
4
|
+
orbital TagStripOrbital {
|
|
5
|
+
type TagStripOptions = Event { data : [StripTag] } "The shared tag store loaded for the strip's display pass"
|
|
6
|
+
|
|
7
|
+
type TagStripAddOptions = Event { data : [StripTag] } "The shared tag store loaded to resolve a typed tag name on add"
|
|
8
|
+
|
|
9
|
+
type TagStripRemoveOptions = Event { data : [StripTag] } "The shared tag store loaded to resolve the remaining names on remove"
|
|
10
|
+
|
|
11
|
+
type TagStripTagCreated = Event { id : string, row : StripTag } "A typed tag name had no existing row; one was created in the shared taxonomy"
|
|
12
|
+
|
|
13
|
+
type TagStripLoadFailed = Event { error : string, code : string } "The tag store fetch or create failed"
|
|
14
|
+
|
|
15
|
+
entity StripTag [persistent: tags] {
|
|
16
|
+
id : string!
|
|
17
|
+
name : string! @description "The descriptive label for this tag." @synonyms "label, title"
|
|
18
|
+
parentId : StripTag @description "Reference to the parent tag in the hierarchy; empty marks a root." @synonyms "parent, ancestor"
|
|
19
|
+
createdAt : string = ""
|
|
20
|
+
pendingId : string = ""
|
|
21
|
+
docId : string @intrinsic @description "The open record's id, stashed at SHOW_TAG_STRIP so commits know which row to update." @synonyms "record id, scope id" = ""
|
|
22
|
+
docTagIds : [string] @intrinsic @description "The open record's current tag ids, stashed at SHOW_TAG_STRIP for membership tests." @synonyms "attached tags, current tags"
|
|
23
|
+
pendingTagName : string @intrinsic @description "The tag name typed or clicked on add, held across the resolve fetch." @synonyms "typed tag, adding tag" = ""
|
|
24
|
+
pendingNames : [string] @intrinsic @description "The chip names remaining after a remove, held across the resolve fetch." @synonyms "remaining tags, kept names"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
trait TagStrip -> @rebindable StripTag [interaction, collection] {
|
|
28
|
+
initial: idle
|
|
29
|
+
|
|
30
|
+
state idle {
|
|
31
|
+
INIT -> idle
|
|
32
|
+
(fetch StripTag {
|
|
33
|
+
emit: { failure: TagStripLoadFailed, success: TagStripOptions }
|
|
34
|
+
})
|
|
35
|
+
;; Pre-scope paint: the store is warm but no record is open yet.
|
|
36
|
+
TagStripOptions -> idle
|
|
37
|
+
TagStripLoadFailed -> idle
|
|
38
|
+
SHOW_TAG_STRIP -> loading
|
|
39
|
+
(set @entity.docId ?id)
|
|
40
|
+
(set @entity.docTagIds (array/map ?tagIds (fn t (str/default (object/get @t id) @t))))
|
|
41
|
+
(fetch StripTag {
|
|
42
|
+
emit: { failure: TagStripLoadFailed, success: TagStripOptions }
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
state loading {
|
|
47
|
+
SHOW_TAG_STRIP -> loading
|
|
48
|
+
(set @entity.docId ?id)
|
|
49
|
+
(set @entity.docTagIds (array/map ?tagIds (fn t (str/default (object/get @t id) @t))))
|
|
50
|
+
(fetch StripTag {
|
|
51
|
+
emit: { failure: TagStripLoadFailed, success: TagStripOptions }
|
|
52
|
+
})
|
|
53
|
+
TagStripOptions -> ready
|
|
54
|
+
(render-ui main {
|
|
55
|
+
children: [(if ["!=", @config.title, ""] {
|
|
56
|
+
color: muted
|
|
57
|
+
content: @config.title
|
|
58
|
+
type: typography
|
|
59
|
+
variant: caption
|
|
60
|
+
} null), {
|
|
61
|
+
addEvent: ADD_TAG
|
|
62
|
+
helperText: @config.helperText
|
|
63
|
+
placeholder: @config.placeholder
|
|
64
|
+
removeEvent: REMOVE_TAG
|
|
65
|
+
type: tag-input
|
|
66
|
+
value: (array/map (array/filter ?data (fn t (array/includes @entity.docTagIds (object/get @t id)))) (fn t (object/get @t name)))
|
|
67
|
+
variant: secondary
|
|
68
|
+
}, (if ["=", (array/len (array/filter ?data (fn t (if (array/includes @entity.docTagIds (object/get @t id)) false true)))), 0] null {
|
|
69
|
+
children: (array/map (array/filter ?data (fn t (if (array/includes @entity.docTagIds (object/get @t id)) false true))) (fn t {
|
|
70
|
+
action: ADD_TAG
|
|
71
|
+
actionPayload: { tag: @t.name }
|
|
72
|
+
icon: tag
|
|
73
|
+
label: @t.name
|
|
74
|
+
size: sm
|
|
75
|
+
type: button
|
|
76
|
+
variant: ghost
|
|
77
|
+
}))
|
|
78
|
+
className: flex-wrap
|
|
79
|
+
direction: horizontal
|
|
80
|
+
gap: xs
|
|
81
|
+
type: stack
|
|
82
|
+
})]
|
|
83
|
+
direction: vertical
|
|
84
|
+
gap: xs
|
|
85
|
+
type: stack
|
|
86
|
+
})
|
|
87
|
+
TagStripLoadFailed -> idle
|
|
88
|
+
(render-ui main {
|
|
89
|
+
message: ?error
|
|
90
|
+
type: alert
|
|
91
|
+
variant: error
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
state ready {
|
|
96
|
+
SHOW_TAG_STRIP -> loading
|
|
97
|
+
(set @entity.docId ?id)
|
|
98
|
+
(set @entity.docTagIds (array/map ?tagIds (fn t (str/default (object/get @t id) @t))))
|
|
99
|
+
(fetch StripTag {
|
|
100
|
+
emit: { failure: TagStripLoadFailed, success: TagStripOptions }
|
|
101
|
+
})
|
|
102
|
+
ADD_TAG -> adding
|
|
103
|
+
(set @entity.pendingTagName ?tag)
|
|
104
|
+
(fetch StripTag {
|
|
105
|
+
emit: { failure: TagStripLoadFailed, success: TagStripAddOptions }
|
|
106
|
+
})
|
|
107
|
+
(render-ui main {
|
|
108
|
+
align: center
|
|
109
|
+
children: [{ size: sm, type: spinner }]
|
|
110
|
+
direction: horizontal
|
|
111
|
+
gap: xs
|
|
112
|
+
type: stack
|
|
113
|
+
})
|
|
114
|
+
REMOVE_TAG -> removing
|
|
115
|
+
(set @entity.pendingNames ?value)
|
|
116
|
+
(fetch StripTag {
|
|
117
|
+
emit: { failure: TagStripLoadFailed, success: TagStripRemoveOptions }
|
|
118
|
+
})
|
|
119
|
+
(render-ui main {
|
|
120
|
+
align: center
|
|
121
|
+
children: [{ size: sm, type: spinner }]
|
|
122
|
+
direction: horizontal
|
|
123
|
+
gap: xs
|
|
124
|
+
type: stack
|
|
125
|
+
})
|
|
126
|
+
TagStripTagCreated -> ready
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
state adding {
|
|
130
|
+
SHOW_TAG_STRIP -> loading
|
|
131
|
+
(set @entity.docId ?id)
|
|
132
|
+
(set @entity.docTagIds (array/map ?tagIds (fn t (str/default (object/get @t id) @t))))
|
|
133
|
+
(fetch StripTag {
|
|
134
|
+
emit: { failure: TagStripLoadFailed, success: TagStripOptions }
|
|
135
|
+
})
|
|
136
|
+
;; The typed name matches an existing tag — attach its id.
|
|
137
|
+
TagStripAddOptions -> ready when (array/includes (array/map ?data (fn t (object/get @t name))) @entity.pendingTagName)
|
|
138
|
+
(emit TAGS_CHANGED {
|
|
139
|
+
id: @entity.docId
|
|
140
|
+
tagIds: (array/append @entity.docTagIds (object/get (array/first (array/filter ?data (fn t ["=", (object/get @t name), @entity.pendingTagName]))) id))
|
|
141
|
+
})
|
|
142
|
+
;; Unknown name — create it in the shared taxonomy, then attach.
|
|
143
|
+
TagStripAddOptions -> creating
|
|
144
|
+
(persist create StripTag { name: @entity.pendingTagName } {
|
|
145
|
+
emit: { failure: TagStripLoadFailed, success: TagStripTagCreated }
|
|
146
|
+
})
|
|
147
|
+
TagStripLoadFailed -> idle
|
|
148
|
+
(render-ui main {
|
|
149
|
+
message: ?error
|
|
150
|
+
type: alert
|
|
151
|
+
variant: error
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
state creating {
|
|
156
|
+
SHOW_TAG_STRIP -> loading
|
|
157
|
+
(set @entity.docId ?id)
|
|
158
|
+
(set @entity.docTagIds (array/map ?tagIds (fn t (str/default (object/get @t id) @t))))
|
|
159
|
+
(fetch StripTag {
|
|
160
|
+
emit: { failure: TagStripLoadFailed, success: TagStripOptions }
|
|
161
|
+
})
|
|
162
|
+
TagStripTagCreated -> ready when ["!=", (str/default ?id ""), ""]
|
|
163
|
+
(emit TAGS_CHANGED {
|
|
164
|
+
id: @entity.docId
|
|
165
|
+
tagIds: (array/append @entity.docTagIds ?id)
|
|
166
|
+
})
|
|
167
|
+
TagStripLoadFailed -> idle
|
|
168
|
+
(render-ui main {
|
|
169
|
+
message: ?error
|
|
170
|
+
type: alert
|
|
171
|
+
variant: error
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
state removing {
|
|
176
|
+
SHOW_TAG_STRIP -> loading
|
|
177
|
+
(set @entity.docId ?id)
|
|
178
|
+
(set @entity.docTagIds (array/map ?tagIds (fn t (str/default (object/get @t id) @t))))
|
|
179
|
+
(fetch StripTag {
|
|
180
|
+
emit: { failure: TagStripLoadFailed, success: TagStripOptions }
|
|
181
|
+
})
|
|
182
|
+
;; The remaining chip names map back to ids — every kept name exists
|
|
183
|
+
;; by construction (chips only render attached, existing tags).
|
|
184
|
+
TagStripRemoveOptions -> ready
|
|
185
|
+
(emit TAGS_CHANGED {
|
|
186
|
+
id: @entity.docId
|
|
187
|
+
tagIds: (array/map (array/filter ?data (fn t (array/includes @entity.pendingNames (object/get @t name)))) (fn t (object/get @t id)))
|
|
188
|
+
})
|
|
189
|
+
TagStripLoadFailed -> idle
|
|
190
|
+
(render-ui main {
|
|
191
|
+
message: ?error
|
|
192
|
+
type: alert
|
|
193
|
+
variant: error
|
|
194
|
+
})
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
emits {
|
|
198
|
+
TAGS_CHANGED -> external {
|
|
199
|
+
id : string
|
|
200
|
+
tagIds : [string]
|
|
201
|
+
}
|
|
202
|
+
@description "The record's tag set changed (chip added or removed); the host routes this into its persistor's update so the write and the refetch stay the organism's."
|
|
203
|
+
@synonyms "tags updated, tag set changed, retagged"
|
|
204
|
+
@tier "domain"
|
|
205
|
+
ADD_TAG {
|
|
206
|
+
tag : string!
|
|
207
|
+
}
|
|
208
|
+
@description "A tag name was typed into the strip or an existing tag's suggestion chip was clicked."
|
|
209
|
+
@synonyms "attach tag, add label"
|
|
210
|
+
@tier "presentation"
|
|
211
|
+
REMOVE_TAG {
|
|
212
|
+
tag : string
|
|
213
|
+
value : [string]
|
|
214
|
+
}
|
|
215
|
+
@description "A chip's remove affordance was clicked; value carries the names that remain."
|
|
216
|
+
@synonyms "detach tag, remove label"
|
|
217
|
+
@tier "presentation"
|
|
218
|
+
TagStripOptions {
|
|
219
|
+
data : [StripTag]
|
|
220
|
+
}
|
|
221
|
+
@description "The shared tag store loaded for the display pass."
|
|
222
|
+
@tier "internal"
|
|
223
|
+
TagStripAddOptions {
|
|
224
|
+
data : [StripTag]
|
|
225
|
+
}
|
|
226
|
+
@description "The shared tag store loaded to resolve a typed name on add."
|
|
227
|
+
@tier "internal"
|
|
228
|
+
TagStripRemoveOptions {
|
|
229
|
+
data : [StripTag]
|
|
230
|
+
}
|
|
231
|
+
@description "The shared tag store loaded to resolve the remaining names on remove."
|
|
232
|
+
@tier "internal"
|
|
233
|
+
TagStripTagCreated {
|
|
234
|
+
id : string
|
|
235
|
+
row : StripTag
|
|
236
|
+
}
|
|
237
|
+
@description "A typed name had no existing tag; a fresh row was created in the shared taxonomy."
|
|
238
|
+
@tier "internal"
|
|
239
|
+
TagStripLoadFailed {
|
|
240
|
+
error : string
|
|
241
|
+
code : string
|
|
242
|
+
}
|
|
243
|
+
@description "The tag store fetch or create failed."
|
|
244
|
+
@tier "internal"
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
listens {
|
|
248
|
+
SHOW_TAG_STRIP {
|
|
249
|
+
id : string!
|
|
250
|
+
tagIds : [string]
|
|
251
|
+
}
|
|
252
|
+
@description "Scope the strip to the open record — routed from the document's load events; carries the record's id and current tag ids (hydrated tag rows are normalized to their ids at stash time, so include-hydrated fetches route straight through)."
|
|
253
|
+
@synonyms "load tags, scope tag strip, show tags"
|
|
254
|
+
@tier "domain"
|
|
255
|
+
ADD_TAG {
|
|
256
|
+
tag : string!
|
|
257
|
+
}
|
|
258
|
+
@description "Attach a tag by name — typed into the input or clicked from the existing-tag chips."
|
|
259
|
+
@synonyms "attach tag, add label"
|
|
260
|
+
@tier "presentation"
|
|
261
|
+
REMOVE_TAG {
|
|
262
|
+
tag : string
|
|
263
|
+
value : [string]
|
|
264
|
+
}
|
|
265
|
+
@description "Detach a chip; value carries the names that remain."
|
|
266
|
+
@synonyms "detach tag, remove label"
|
|
267
|
+
@tier "presentation"
|
|
268
|
+
TagStripOptions {
|
|
269
|
+
data : [StripTag]
|
|
270
|
+
}
|
|
271
|
+
@description "Display-pass fetch resolved."
|
|
272
|
+
@tier "internal"
|
|
273
|
+
TagStripAddOptions {
|
|
274
|
+
data : [StripTag]
|
|
275
|
+
}
|
|
276
|
+
@description "Add-resolve fetch resolved."
|
|
277
|
+
@tier "internal"
|
|
278
|
+
TagStripRemoveOptions {
|
|
279
|
+
data : [StripTag]
|
|
280
|
+
}
|
|
281
|
+
@description "Remove-resolve fetch resolved."
|
|
282
|
+
@tier "internal"
|
|
283
|
+
TagStripTagCreated {
|
|
284
|
+
id : string
|
|
285
|
+
row : StripTag
|
|
286
|
+
}
|
|
287
|
+
@description "The taxonomy row for a typed name persisted; attach its id."
|
|
288
|
+
@tier "internal"
|
|
289
|
+
TagStripLoadFailed {
|
|
290
|
+
error : string
|
|
291
|
+
code : string
|
|
292
|
+
}
|
|
293
|
+
@description "The tag store fetch or create failed."
|
|
294
|
+
@tier "internal"
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
config {
|
|
298
|
+
title : string = Tags
|
|
299
|
+
@label "Strip caption"
|
|
300
|
+
@description "Small caption above the chips; empty hides it"
|
|
301
|
+
@tier "presentation"
|
|
302
|
+
placeholder : string = "Add a tag…"
|
|
303
|
+
@label "Input placeholder"
|
|
304
|
+
@description "Placeholder in the type-to-add input"
|
|
305
|
+
@tier "presentation"
|
|
306
|
+
helperText : string = ""
|
|
307
|
+
@label "Helper text"
|
|
308
|
+
@description "Optional helper line under the input"
|
|
309
|
+
@tier "presentation"
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
page "/tagstrip/demo" as TagStripDemoPage -> TagStrip
|
|
314
|
+
}
|
|
@@ -7,6 +7,8 @@ orbital TagTaxonomyOrbital {
|
|
|
7
7
|
|
|
8
8
|
type TagSelected = Event { tagId : string! } "Fired when a tag is selected to drill into its children"
|
|
9
9
|
|
|
10
|
+
type TagCommit = { name : string!, parentId : string }
|
|
11
|
+
|
|
10
12
|
entity Tag [persistent: tags] {
|
|
11
13
|
id : string!
|
|
12
14
|
name : string! @description "The descriptive label for this item." @synonyms "label, title, description"
|
|
@@ -21,6 +23,11 @@ orbital TagTaxonomyOrbital {
|
|
|
21
23
|
initial: loading
|
|
22
24
|
|
|
23
25
|
state loading {
|
|
26
|
+
LEVEL_RELOAD -> loading
|
|
27
|
+
(fetch Tag {
|
|
28
|
+
filter: ["=", (object/get @entity parentId), (str/default ?tagId "")]
|
|
29
|
+
emit: { failure: TagLoadFailed, success: TagLoaded }
|
|
30
|
+
})
|
|
24
31
|
INIT -> loading
|
|
25
32
|
(set @entity.id "")
|
|
26
33
|
(set @entity.parentId "")
|
|
@@ -32,7 +39,7 @@ orbital TagTaxonomyOrbital {
|
|
|
32
39
|
align: center
|
|
33
40
|
children: [{ type: spinner }, {
|
|
34
41
|
color: muted
|
|
35
|
-
content: "Loading
|
|
42
|
+
content: "Loading…"
|
|
36
43
|
type: typography
|
|
37
44
|
variant: caption
|
|
38
45
|
}]
|
|
@@ -47,7 +54,7 @@ orbital TagTaxonomyOrbital {
|
|
|
47
54
|
action: SHOW_ROOT
|
|
48
55
|
disabled: (if (!= @entity.id "") false true)
|
|
49
56
|
icon: arrow-left
|
|
50
|
-
label:
|
|
57
|
+
label: @config.rootLabel
|
|
51
58
|
size: sm
|
|
52
59
|
type: button
|
|
53
60
|
variant: ghost
|
|
@@ -55,7 +62,14 @@ orbital TagTaxonomyOrbital {
|
|
|
55
62
|
content: @config.title
|
|
56
63
|
type: typography
|
|
57
64
|
variant: h3
|
|
58
|
-
}, {
|
|
65
|
+
}, (if @config.allowEdit {
|
|
66
|
+
action: NEW_TAG
|
|
67
|
+
icon: plus
|
|
68
|
+
label: @config.createLabel
|
|
69
|
+
size: sm
|
|
70
|
+
type: button
|
|
71
|
+
variant: secondary
|
|
72
|
+
} null), {
|
|
59
73
|
entity: ?data
|
|
60
74
|
fields: []
|
|
61
75
|
gap: sm
|
|
@@ -136,7 +150,7 @@ orbital TagTaxonomyOrbital {
|
|
|
136
150
|
align: center
|
|
137
151
|
children: [{ type: spinner }, {
|
|
138
152
|
color: muted
|
|
139
|
-
content: "Loading
|
|
153
|
+
content: "Loading…"
|
|
140
154
|
type: typography
|
|
141
155
|
variant: caption
|
|
142
156
|
}]
|
|
@@ -157,7 +171,7 @@ orbital TagTaxonomyOrbital {
|
|
|
157
171
|
align: center
|
|
158
172
|
children: [{ type: spinner }, {
|
|
159
173
|
color: muted
|
|
160
|
-
content: "Loading
|
|
174
|
+
content: "Loading…"
|
|
161
175
|
type: typography
|
|
162
176
|
variant: caption
|
|
163
177
|
}]
|
|
@@ -177,7 +191,7 @@ orbital TagTaxonomyOrbital {
|
|
|
177
191
|
align: center
|
|
178
192
|
children: [{ type: spinner }, {
|
|
179
193
|
color: muted
|
|
180
|
-
content: "Loading
|
|
194
|
+
content: "Loading…"
|
|
181
195
|
type: typography
|
|
182
196
|
variant: caption
|
|
183
197
|
}]
|
|
@@ -192,7 +206,7 @@ orbital TagTaxonomyOrbital {
|
|
|
192
206
|
action: SHOW_ROOT
|
|
193
207
|
disabled: (if (!= @entity.id "") false true)
|
|
194
208
|
icon: arrow-left
|
|
195
|
-
label:
|
|
209
|
+
label: @config.rootLabel
|
|
196
210
|
size: sm
|
|
197
211
|
type: button
|
|
198
212
|
variant: ghost
|
|
@@ -200,7 +214,14 @@ orbital TagTaxonomyOrbital {
|
|
|
200
214
|
content: @config.title
|
|
201
215
|
type: typography
|
|
202
216
|
variant: h3
|
|
203
|
-
}, {
|
|
217
|
+
}, (if @config.allowEdit {
|
|
218
|
+
action: NEW_TAG
|
|
219
|
+
icon: plus
|
|
220
|
+
label: @config.createLabel
|
|
221
|
+
size: sm
|
|
222
|
+
type: button
|
|
223
|
+
variant: secondary
|
|
224
|
+
} null), {
|
|
204
225
|
entity: ?data
|
|
205
226
|
fields: []
|
|
206
227
|
gap: sm
|
|
@@ -261,6 +282,29 @@ orbital TagTaxonomyOrbital {
|
|
|
261
282
|
gap: md
|
|
262
283
|
type: stack
|
|
263
284
|
})
|
|
285
|
+
NEW_TAG -> creating when @config.allowEdit
|
|
286
|
+
(render-ui modal {
|
|
287
|
+
children: [{
|
|
288
|
+
content: @config.createLabel
|
|
289
|
+
type: typography
|
|
290
|
+
variant: h3
|
|
291
|
+
}, {
|
|
292
|
+
color: muted
|
|
293
|
+
content: (if (!= @entity.id "") "Created inside the open category." "Created at the top level.")
|
|
294
|
+
type: typography
|
|
295
|
+
variant: caption
|
|
296
|
+
}, { type: divider }, {
|
|
297
|
+
cancelEvent: CANCEL_TAG
|
|
298
|
+
entity: { parentId: @entity.id }
|
|
299
|
+
fields: (name)
|
|
300
|
+
mode: create
|
|
301
|
+
submitEvent: COMMIT_TAG
|
|
302
|
+
type: form-section
|
|
303
|
+
}]
|
|
304
|
+
direction: vertical
|
|
305
|
+
gap: md
|
|
306
|
+
type: stack
|
|
307
|
+
})
|
|
264
308
|
TagLoadFailed -> error
|
|
265
309
|
(render-ui main {
|
|
266
310
|
message: ?error
|
|
@@ -269,6 +313,61 @@ orbital TagTaxonomyOrbital {
|
|
|
269
313
|
})
|
|
270
314
|
}
|
|
271
315
|
|
|
316
|
+
state creating {
|
|
317
|
+
COMMIT_TAG -> creating
|
|
318
|
+
(persist create Tag {
|
|
319
|
+
name: (object/get ?data name)
|
|
320
|
+
parentId: (str/default (object/get ?data parentId) "")
|
|
321
|
+
} {
|
|
322
|
+
emit: { failure: TagCreateFailed, success: TagCreated }
|
|
323
|
+
})
|
|
324
|
+
;; A filter expression binds @entity to the candidate ROW, so the open
|
|
325
|
+
;; level must travel by payload: the arm emits LEVEL_RELOAD carrying the
|
|
326
|
+
;; trait's own level id, and loading refetches from it.
|
|
327
|
+
CANCEL_TAG -> loading
|
|
328
|
+
(render-ui modal null)
|
|
329
|
+
(render-ui main {
|
|
330
|
+
align: center
|
|
331
|
+
children: [{ type: spinner }, {
|
|
332
|
+
color: muted
|
|
333
|
+
content: "Loading…"
|
|
334
|
+
type: typography
|
|
335
|
+
variant: caption
|
|
336
|
+
}]
|
|
337
|
+
className: py-12
|
|
338
|
+
direction: vertical
|
|
339
|
+
gap: md
|
|
340
|
+
type: stack
|
|
341
|
+
})
|
|
342
|
+
(emit LEVEL_RELOAD { tagId: @entity.id })
|
|
343
|
+
;; Refetch the level the new tag landed on — its own parentId names it.
|
|
344
|
+
TagCreated -> loading
|
|
345
|
+
(render-ui modal null)
|
|
346
|
+
(render-ui main {
|
|
347
|
+
align: center
|
|
348
|
+
children: [{ type: spinner }, {
|
|
349
|
+
color: muted
|
|
350
|
+
content: "Loading…"
|
|
351
|
+
type: typography
|
|
352
|
+
variant: caption
|
|
353
|
+
}]
|
|
354
|
+
className: py-12
|
|
355
|
+
direction: vertical
|
|
356
|
+
gap: md
|
|
357
|
+
type: stack
|
|
358
|
+
})
|
|
359
|
+
(fetch Tag {
|
|
360
|
+
filter: ["=", (object/get @entity parentId), (str/default (object/get ?row parentId) "")]
|
|
361
|
+
emit: { failure: TagLoadFailed, success: TagLoaded }
|
|
362
|
+
})
|
|
363
|
+
TagCreateFailed -> creating
|
|
364
|
+
(render-ui modal {
|
|
365
|
+
message: ?error
|
|
366
|
+
type: alert
|
|
367
|
+
variant: error
|
|
368
|
+
})
|
|
369
|
+
}
|
|
370
|
+
|
|
272
371
|
state editing {
|
|
273
372
|
INIT -> loading
|
|
274
373
|
(set @entity.id "")
|
|
@@ -281,7 +380,7 @@ orbital TagTaxonomyOrbital {
|
|
|
281
380
|
align: center
|
|
282
381
|
children: [{ type: spinner }, {
|
|
283
382
|
color: muted
|
|
284
|
-
content: "Loading
|
|
383
|
+
content: "Loading…"
|
|
285
384
|
type: typography
|
|
286
385
|
variant: caption
|
|
287
386
|
}]
|
|
@@ -303,7 +402,7 @@ orbital TagTaxonomyOrbital {
|
|
|
303
402
|
action: SHOW_ROOT
|
|
304
403
|
disabled: (if (!= @entity.id "") false true)
|
|
305
404
|
icon: arrow-left
|
|
306
|
-
label:
|
|
405
|
+
label: @config.rootLabel
|
|
307
406
|
size: sm
|
|
308
407
|
type: button
|
|
309
408
|
variant: ghost
|
|
@@ -311,7 +410,14 @@ orbital TagTaxonomyOrbital {
|
|
|
311
410
|
content: @config.title
|
|
312
411
|
type: typography
|
|
313
412
|
variant: h3
|
|
314
|
-
}, {
|
|
413
|
+
}, (if @config.allowEdit {
|
|
414
|
+
action: NEW_TAG
|
|
415
|
+
icon: plus
|
|
416
|
+
label: @config.createLabel
|
|
417
|
+
size: sm
|
|
418
|
+
type: button
|
|
419
|
+
variant: secondary
|
|
420
|
+
} null), {
|
|
315
421
|
entity: ?data
|
|
316
422
|
fields: []
|
|
317
423
|
gap: sm
|
|
@@ -392,7 +498,7 @@ orbital TagTaxonomyOrbital {
|
|
|
392
498
|
align: center
|
|
393
499
|
children: [{ type: spinner }, {
|
|
394
500
|
color: muted
|
|
395
|
-
content: "Loading
|
|
501
|
+
content: "Loading…"
|
|
396
502
|
type: typography
|
|
397
503
|
variant: caption
|
|
398
504
|
}]
|
|
@@ -429,6 +535,39 @@ orbital TagTaxonomyOrbital {
|
|
|
429
535
|
@description "Signals a tag has been chosen for further exploration."
|
|
430
536
|
@synonyms "chosen, picked, activated, highlighted"
|
|
431
537
|
@tier "domain"
|
|
538
|
+
NEW_TAG
|
|
539
|
+
@description "Opens the create-tag form (rendered only when allowEdit is on); the creation lands at the level currently open."
|
|
540
|
+
@synonyms "add tag, create category, new category"
|
|
541
|
+
@tier "domain"
|
|
542
|
+
COMMIT_TAG {
|
|
543
|
+
data : TagCommit
|
|
544
|
+
}
|
|
545
|
+
@description "The new-category form committed; data carries the name and the parent level."
|
|
546
|
+
@synonyms "save tag, create tag"
|
|
547
|
+
@tier "internal"
|
|
548
|
+
CANCEL_TAG
|
|
549
|
+
@description "The new-category form was dismissed without creating."
|
|
550
|
+
@synonyms "cancel, back"
|
|
551
|
+
@tier "internal"
|
|
552
|
+
LEVEL_RELOAD {
|
|
553
|
+
tagId : string
|
|
554
|
+
}
|
|
555
|
+
@description "Internal hop that refetches the open level after the new-category form closes (a fetch filter cannot read trait state, so the level travels by payload)."
|
|
556
|
+
@synonyms "reload level, refresh"
|
|
557
|
+
@tier "internal"
|
|
558
|
+
TagCreated {
|
|
559
|
+
row : Tag
|
|
560
|
+
}
|
|
561
|
+
@description "A new tag row persisted; the open level refetches to show it."
|
|
562
|
+
@synonyms "created, added"
|
|
563
|
+
@tier "internal"
|
|
564
|
+
TagCreateFailed {
|
|
565
|
+
error : string
|
|
566
|
+
code : string
|
|
567
|
+
}
|
|
568
|
+
@description "The tag create failed."
|
|
569
|
+
@synonyms "error, failure"
|
|
570
|
+
@tier "internal"
|
|
432
571
|
}
|
|
433
572
|
|
|
434
573
|
listens {
|
|
@@ -457,6 +596,39 @@ orbital TagTaxonomyOrbital {
|
|
|
457
596
|
@description "A tag in the taxonomy has been chosen by the user."
|
|
458
597
|
@synonyms "chosen, picked, activated, selected"
|
|
459
598
|
@tier "domain"
|
|
599
|
+
NEW_TAG
|
|
600
|
+
@description "The New-category affordance was clicked."
|
|
601
|
+
@synonyms "add tag, create category"
|
|
602
|
+
@tier "domain"
|
|
603
|
+
COMMIT_TAG {
|
|
604
|
+
data : TagCommit
|
|
605
|
+
}
|
|
606
|
+
@description "The new-category form committed."
|
|
607
|
+
@synonyms "save tag, create tag"
|
|
608
|
+
@tier "internal"
|
|
609
|
+
CANCEL_TAG
|
|
610
|
+
@description "The new-category form was dismissed."
|
|
611
|
+
@synonyms "cancel, back"
|
|
612
|
+
@tier "internal"
|
|
613
|
+
LEVEL_RELOAD {
|
|
614
|
+
tagId : string
|
|
615
|
+
}
|
|
616
|
+
@description "Refetch the open level."
|
|
617
|
+
@synonyms "reload level, refresh"
|
|
618
|
+
@tier "internal"
|
|
619
|
+
TagCreated {
|
|
620
|
+
row : Tag
|
|
621
|
+
}
|
|
622
|
+
@description "A new tag row persisted."
|
|
623
|
+
@synonyms "created, added"
|
|
624
|
+
@tier "internal"
|
|
625
|
+
TagCreateFailed {
|
|
626
|
+
error : string
|
|
627
|
+
code : string
|
|
628
|
+
}
|
|
629
|
+
@description "The tag create failed."
|
|
630
|
+
@synonyms "error, failure"
|
|
631
|
+
@tier "internal"
|
|
460
632
|
}
|
|
461
633
|
|
|
462
634
|
config {
|
|
@@ -466,8 +638,18 @@ orbital TagTaxonomyOrbital {
|
|
|
466
638
|
@tier "presentation"
|
|
467
639
|
allowEdit : boolean = false
|
|
468
640
|
@label "Allow editing"
|
|
469
|
-
@description "
|
|
641
|
+
@description "Render the create-tag affordance: creations land at the level currently open (top level, or inside the drilled-into category). Rename is a follow-up (ledgered)."
|
|
470
642
|
@tier "domain"
|
|
643
|
+
createLabel : string = "New tag"
|
|
644
|
+
@label "Create-button label"
|
|
645
|
+
@description "Label on the create affordance and its form heading — say what this taxonomy calls its entries (New tag, New category, New topic)."
|
|
646
|
+
@synonyms "add label, new tag label, create caption"
|
|
647
|
+
@tier "presentation"
|
|
648
|
+
rootLabel : string = "All tags"
|
|
649
|
+
@label "Back-to-root label"
|
|
650
|
+
@description "Label on the back affordance that returns from a drilled-in level to the root — phrase it in this taxonomy's vocabulary (All tags, All categories)."
|
|
651
|
+
@synonyms "back label, root caption, all label"
|
|
652
|
+
@tier "presentation"
|
|
471
653
|
tableLook : "dense" | "spacious" | "striped" | "borderless" | "card-rows" = dense
|
|
472
654
|
@label "Table look"
|
|
473
655
|
@description "Layer 2 visual treatment for the data table rendered by this atom."
|