@elaraai/e3-ui 1.0.59 → 1.0.61

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.
@@ -10,11 +10,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "@elaraai/e3-ui/jsx-runtime";
10
10
  * surfacing the pending changes for sign-off.
11
11
  *
12
12
  * Coverage:
13
- * 1. Slider-driven editor → workforcePolicyEditor
14
- * 2. Heterogeneous inputsserviceConfigForm
15
- * 3. Editable Table cells → rosterTableEditor
16
- * 4. Mixed sliders + inputs pricingRulesEditor (side-by-side mode)
17
- * 5. Minimal call site → diffDefaults (IR-roundtrip)
13
+ * 1. Slider-driven editor → workforcePolicyEditor
14
+ * 2. Editor variants paneldiffEditorVariants (heterogeneous inputs /
15
+ * mixed sliders + inputs / Set / Dict / Variant / density presets)
16
+ * 3. Editable Table cells rosterTableEditor
17
+ * 4. Minimal call site → diffDefaults (IR-roundtrip)
18
+ * 5. Merge-conflict chooser → mergeConflictDemo
19
+ * 6. Overlay-mode patches → diffOverlayVariants
20
+ * 7. Staged + patch datasets → diffStagedPatchVariants
18
21
  *
19
22
  * Pattern:
20
23
  * 1. Declare an `e3.input(name, type, default)` per editable scalar.
@@ -25,7 +28,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "@elaraai/e3-ui/jsx-runtime";
25
28
  * the merged batch; Discard drops the buffer.
26
29
  */
27
30
  import { East, FloatType, IntegerType, StringType, BooleanType, DateTimeType, ArrayType, StructType, SetType, DictType, VariantType, NullType, FunctionType, PatchType, diffFor, some, variant, example, } from "@elaraai/east";
28
- import { Card, HStack, VStack, Slider, Input, Switch, Select, Text, Button, Reactive, Table, UIComponentType, } from "@elaraai/east-ui";
31
+ import { Card, HStack, VStack, Slider, Input, Switch, Select, Separator, Text, Button, Reactive, Table, UIComponentType, } from "@elaraai/east-ui";
29
32
  import { Data, Diff } from "@elaraai/e3-ui";
30
33
  import * as e3 from "@elaraai/e3";
31
34
  // ============================================================================
@@ -102,25 +105,84 @@ export const workforcePolicyEditor = example({
102
105
  inputs: [],
103
106
  });
104
107
  // ============================================================================
105
- // 2. Service-config formheterogeneous Inputs (String / Integer / DateTime),
106
- // Switch, Select; commit fires a Toast.
108
+ // 2. Editor variants panel the type-coverage enumeration: heterogeneous
109
+ // scalar inputs (String / Integer / Bool / DateTime / Select), mixed
110
+ // sliders + inputs (side-by-side Diff), Set / Dict / Variant bindings,
111
+ // and the two non-default density presets.
107
112
  // ============================================================================
108
- export const serviceConfigForm = example({
109
- keywords: ["Diff", "Input", "Switch", "Select", "DateTime", "Toast", "onCommitted"],
110
- description: "Service-config form covering String / Integer / Bool / DateTime / Select; commit fires a success Toast",
113
+ export const diffEditorVariants = example({
114
+ keywords: ["Diff", "Input", "Switch", "Select", "DateTime", "Toast", "onCommitted", "side-by-side", "Slider", "pricing", "discount", "mixed", "Set", "feature flags", "bindStaged", "Dict", "regional pricing", "Variant", "Button", "deployment status", "density", "compact", "condensed"],
115
+ description: "Editor variant panel — SERVICE CONFIG FORM: heterogeneous String / Integer / Bool / DateTime / Select inputs, commit fires a success Toast; PRICING RULES: sliders for list price/discount, IntegerInput for min order qty, StringInput for currency, Diff in side-by-side mode; FEATURE FLAGS: Switch per known flag toggles inclusion in a staged Set, Diff shows insertions / deletions; REGIONAL PRICING: Input.Float per region writes back to a staged Dict, Diff shows per-key updates; DEPLOYMENT STATUS: buttons set a Variant binding, Diff shows the status tag change; PRICING RULES COMPACT: `density: \"compact\"` — denser rows; PRICING RULES CONDENSED: `density: \"condensed\"` — mission-control sizing for read-heavy views",
111
116
  fn: East.function([], UIComponentType, (_$) => {
112
- return (_jsx(Reactive, { children: $ => {
113
- const svcName = $.let(Data.bind(serviceNameInput, { mode: "staged" }));
114
- const replicas = $.let(Data.bind(replicasInput, { mode: "staged" }));
115
- const autoScale = $.let(Data.bind(autoScaleInput, { mode: "staged" }));
116
- const region = $.let(Data.bind(regionInput, { mode: "staged" }));
117
- const deployAfter = $.let(Data.bind(deployAfterInput, { mode: "staged" }));
118
- return (_jsx(Card, { children: _jsxs(VStack, { gap: "4", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Service configuration" }), _jsx(Text, { children: "Stage edits across heterogeneous types; on apply you\u2019ll see a confirmation toast." }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "Service name" }), _jsx(Input.String, { value: svcName.read(), placeholder: "service-name", onChange: ($, v) => $(svcName.write(v)) })] }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "Replicas" }), _jsx(Input.Integer, { value: replicas.read(), min: 1n, max: 50n, onChange: ($, v) => $(replicas.write(v)) })] }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "Auto-scale" }), _jsx(Switch, { checked: autoScale.read(), onChange: ($, v) => $(autoScale.write(v)) })] }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "Region" }), _jsx(Select, { value: region.read(), items: [
119
- Select.Item("ap-southeast-2", "ap-southeast-2 (Sydney)"),
120
- Select.Item("us-east-1", "us-east-1 (N. Virginia)"),
121
- Select.Item("eu-west-1", "eu-west-1 (Ireland)"),
122
- ], onChange: ($, v) => $(region.write(v)) })] }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "Deploy after" }), _jsx(Input.DateTime, { value: deployAfter.read(), precision: "datetime", onChange: ($, v) => $(deployAfter.write(v)) })] }), _jsx(Diff, { bindings: [svcName.binding, replicas.binding, autoScale.binding, region.binding, deployAfter.binding] })] }) }));
123
- } }));
117
+ return (_jsxs(VStack, { gap: "4", align: "stretch", children: [_jsx(Separator, { label: "SERVICE CONFIG FORM", align: "start" }), _jsx(Reactive, { children: $ => {
118
+ const svcName = $.let(Data.bind(serviceNameInput, { mode: "staged" }));
119
+ const replicas = $.let(Data.bind(replicasInput, { mode: "staged" }));
120
+ const autoScale = $.let(Data.bind(autoScaleInput, { mode: "staged" }));
121
+ const region = $.let(Data.bind(regionInput, { mode: "staged" }));
122
+ const deployAfter = $.let(Data.bind(deployAfterInput, { mode: "staged" }));
123
+ return (_jsx(Card, { children: _jsxs(VStack, { gap: "4", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Service configuration" }), _jsx(Text, { children: "Stage edits across heterogeneous types; on apply you\u2019ll see a confirmation toast." }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "Service name" }), _jsx(Input.String, { value: svcName.read(), placeholder: "service-name", onChange: ($, v) => $(svcName.write(v)) })] }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "Replicas" }), _jsx(Input.Integer, { value: replicas.read(), min: 1n, max: 50n, onChange: ($, v) => $(replicas.write(v)) })] }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "Auto-scale" }), _jsx(Switch, { checked: autoScale.read(), onChange: ($, v) => $(autoScale.write(v)) })] }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "Region" }), _jsx(Select, { value: region.read(), items: [
124
+ Select.Item("ap-southeast-2", "ap-southeast-2 (Sydney)"),
125
+ Select.Item("us-east-1", "us-east-1 (N. Virginia)"),
126
+ Select.Item("eu-west-1", "eu-west-1 (Ireland)"),
127
+ ], onChange: ($, v) => $(region.write(v)) })] }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "Deploy after" }), _jsx(Input.DateTime, { value: deployAfter.read(), precision: "datetime", onChange: ($, v) => $(deployAfter.write(v)) })] }), _jsx(Diff, { bindings: [svcName.binding, replicas.binding, autoScale.binding, region.binding, deployAfter.binding] })] }) }));
128
+ } }), _jsx(Separator, { label: "PRICING RULES", align: "start" }), _jsx(Reactive, { children: $ => {
129
+ const listPrice = $.let(Data.bind(listPriceInput, { mode: "staged" }));
130
+ const discountPct = $.let(Data.bind(discountPctInput, { mode: "staged" }));
131
+ const minOrderQty = $.let(Data.bind(minOrderQtyInput, { mode: "staged" }));
132
+ const currency = $.let(Data.bind(currencyCodeInput, { mode: "staged" }));
133
+ return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Pricing rules" }), _jsx(Text, { children: "Stage pricing changes \u2014 review side-by-side before applying to the catalog." }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "List price" }), _jsx(Slider, { value: listPrice.read(), min: 0.0, max: 999.95, step: 0.05, onChangeEnd: ($, v) => $(listPrice.write(v)) })] }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "Discount (%)" }), _jsx(Slider, { value: discountPct.read(), min: 0.0, max: 75.0, step: 0.5, onChangeEnd: ($, v) => $(discountPct.write(v)) })] }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "Minimum order quantity" }), _jsx(Input.Integer, { value: minOrderQty.read(), min: 1n, max: 1000n, onChange: ($, v) => $(minOrderQty.write(v)) })] }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "Currency code" }), _jsx(Input.String, { value: currency.read(), placeholder: "AUD", onChange: ($, v) => $(currency.write(v)) })] }), _jsx(Diff, { bindings: [listPrice.binding, discountPct.binding, minOrderQty.binding, currency.binding], hideUnchanged: some(true) })] }) }));
134
+ } }), _jsx(Separator, { label: "FEATURE FLAGS", align: "start" }), _jsx(Reactive, { children: $ => {
135
+ const flags = $.let(Data.bind(featureFlagsInput, { mode: "staged" }));
136
+ const flagsRead = $.let(flags.read(), SetType(StringType));
137
+ // ONE East closure factory: `toggle(flag)` returns the per-switch
138
+ // handler as a real East function value (captures `flag` in East).
139
+ const toggle = $.const(East.function([StringType], FunctionType([BooleanType], NullType), (_$, flag) => East.function([BooleanType], NullType, ($, isOn) => {
140
+ const next = $.let(flags.read(), SetType(StringType));
141
+ $.if(isOn, $ => { $(next.insert(flag)); }).else($ => { $(next.delete(flag)); });
142
+ $(flags.write(next));
143
+ })));
144
+ const onDarkMode = $.const(toggle("dark_mode"));
145
+ const onExperiments = $.const(toggle("experiments"));
146
+ const onNotifications = $.const(toggle("notifications"));
147
+ const onAnalytics = $.const(toggle("analytics"));
148
+ const onAiAssist = $.const(toggle("ai_assist"));
149
+ return (_jsx(Card, { children: _jsxs(VStack, { gap: "4", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Feature flags" }), _jsx(Text, { children: "Toggle flags to stage changes; Diff card below shows the set delta." }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "dark_mode" }), _jsx(Switch, { checked: flagsRead.has("dark_mode"), onChange: onDarkMode })] }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "experiments" }), _jsx(Switch, { checked: flagsRead.has("experiments"), onChange: onExperiments })] }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "notifications" }), _jsx(Switch, { checked: flagsRead.has("notifications"), onChange: onNotifications })] }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "analytics" }), _jsx(Switch, { checked: flagsRead.has("analytics"), onChange: onAnalytics })] }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "ai_assist" }), _jsx(Switch, { checked: flagsRead.has("ai_assist"), onChange: onAiAssist })] }), _jsx(Diff, { bindings: [flags.binding], hideUnchanged: some(true) })] }) }));
150
+ } }), _jsx(Separator, { label: "REGIONAL PRICING", align: "start" }), _jsx(Reactive, { children: $ => {
151
+ const prices = $.let(Data.bind(regionalPricesInput, { mode: "staged" }));
152
+ const pricesRead = $.let(prices.read(), DictType(StringType, FloatType));
153
+ // ONE East closure factory: `setPrice(region)` returns the
154
+ // per-region handler as a real East function value.
155
+ const setPrice = $.const(East.function([StringType], FunctionType([FloatType], NullType), (_$, region) => East.function([FloatType], NullType, ($, newPrice) => {
156
+ const next = $.let(prices.read(), DictType(StringType, FloatType));
157
+ $(next.insertOrUpdate(region, newPrice));
158
+ $(prices.write(next));
159
+ })));
160
+ const onAu = $.const(setPrice("AU"));
161
+ const onUs = $.const(setPrice("US"));
162
+ const onEu = $.const(setPrice("EU"));
163
+ const onJp = $.const(setPrice("JP"));
164
+ return (_jsx(Card, { children: _jsxs(VStack, { gap: "4", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Regional pricing" }), _jsx(Text, { children: "Edit per-region prices; Diff card below tracks pending updates." }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "AU" }), _jsx(Input.Float, { value: pricesRead.get("AU", East.function([StringType], FloatType, _$ => 0.0)), min: 0.0, max: 99999.0, step: 0.05, onChange: onAu })] }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "US" }), _jsx(Input.Float, { value: pricesRead.get("US", East.function([StringType], FloatType, _$ => 0.0)), min: 0.0, max: 99999.0, step: 0.05, onChange: onUs })] }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "EU" }), _jsx(Input.Float, { value: pricesRead.get("EU", East.function([StringType], FloatType, _$ => 0.0)), min: 0.0, max: 99999.0, step: 0.05, onChange: onEu })] }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "JP" }), _jsx(Input.Float, { value: pricesRead.get("JP", East.function([StringType], FloatType, _$ => 0.0)), min: 0.0, max: 99999.0, step: 0.05, onChange: onJp })] }), _jsx(Diff, { bindings: [prices.binding], hideUnchanged: some(true) })] }) }));
165
+ } }), _jsx(Separator, { label: "DEPLOYMENT STATUS", align: "start" }), _jsx(Reactive, { children: $ => {
166
+ const status = $.let(Data.bind(deploymentStatusInput, { mode: "staged" }));
167
+ const statusRead = $.let(status.read(), DeploymentStatusType);
168
+ const setPending = $.const(East.function([], NullType, $ => $(status.write(variant("pending", null)))));
169
+ const setInProgress = $.const(East.function([], NullType, $ => $(status.write(variant("in_progress", null)))));
170
+ const setComplete = $.const(East.function([], NullType, $ => $(status.write(variant("complete", null)))));
171
+ const setFailed = $.const(East.function([], NullType, $ => $(status.write(variant("failed", null)))));
172
+ return (_jsx(Card, { children: _jsxs(VStack, { gap: "4", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Deployment status" }), _jsx(Text, { children: "Current:" }), _jsx(Text, { textStyle: "label-md", children: statusRead.getTag() }), _jsxs(HStack, { gap: "2", children: [_jsx(Button, { onClick: setPending, children: "Pending" }), _jsx(Button, { onClick: setInProgress, children: "In progress" }), _jsx(Button, { onClick: setComplete, children: "Complete" }), _jsx(Button, { onClick: setFailed, children: "Failed" })] }), _jsx(Diff, { bindings: [status.binding], hideUnchanged: some(true) })] }) }));
173
+ } }), _jsx(Separator, { label: "PRICING RULES COMPACT", align: "start" }), _jsx(Reactive, { children: $ => {
174
+ const listPrice = $.let(Data.bind(listPriceInput, { mode: "staged" }));
175
+ const discountPct = $.let(Data.bind(discountPctInput, { mode: "staged" }));
176
+ const minOrderQty = $.let(Data.bind(minOrderQtyInput, { mode: "staged" }));
177
+ const currency = $.let(Data.bind(currencyCodeInput, { mode: "staged" }));
178
+ return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Pricing rules \u2014 compact" }), _jsx(Slider, { value: listPrice.read(), min: 0.0, max: 999.95, step: 0.05, onChangeEnd: ($, v) => $(listPrice.write(v)) }), _jsx(Slider, { value: discountPct.read(), min: 0.0, max: 75.0, step: 0.5, onChangeEnd: ($, v) => $(discountPct.write(v)) }), _jsx(Input.Integer, { value: minOrderQty.read(), min: 1n, max: 1000n, onChange: ($, v) => $(minOrderQty.write(v)) }), _jsx(Input.String, { value: currency.read(), placeholder: "AUD", onChange: ($, v) => $(currency.write(v)) }), _jsx(Diff, { bindings: [listPrice.binding, discountPct.binding, minOrderQty.binding, currency.binding], density: "compact", hideUnchanged: some(true) })] }) }));
179
+ } }), _jsx(Separator, { label: "PRICING RULES CONDENSED", align: "start" }), _jsx(Reactive, { children: $ => {
180
+ const listPrice = $.let(Data.bind(listPriceInput, { mode: "staged" }));
181
+ const discountPct = $.let(Data.bind(discountPctInput, { mode: "staged" }));
182
+ const minOrderQty = $.let(Data.bind(minOrderQtyInput, { mode: "staged" }));
183
+ const currency = $.let(Data.bind(currencyCodeInput, { mode: "staged" }));
184
+ return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Pricing rules \u2014 condensed" }), _jsx(Slider, { value: listPrice.read(), min: 0.0, max: 999.95, step: 0.05, onChangeEnd: ($, v) => $(listPrice.write(v)) }), _jsx(Slider, { value: discountPct.read(), min: 0.0, max: 75.0, step: 0.5, onChangeEnd: ($, v) => $(discountPct.write(v)) }), _jsx(Input.Integer, { value: minOrderQty.read(), min: 1n, max: 1000n, onChange: ($, v) => $(minOrderQty.write(v)) }), _jsx(Input.String, { value: currency.read(), placeholder: "AUD", onChange: ($, v) => $(currency.write(v)) }), _jsx(Diff, { bindings: [listPrice.binding, discountPct.binding, minOrderQty.binding, currency.binding], density: "condensed", hideUnchanged: some(true) })] }) }));
185
+ } })] }));
124
186
  }),
125
187
  inputs: [],
126
188
  });
@@ -173,100 +235,7 @@ export const rosterTableEditor = example({
173
235
  inputs: [],
174
236
  });
175
237
  // ============================================================================
176
- // 4. Pricing-rules editorsliders + integer/string inputs together;
177
- // side-by-side Diff mode for a wider review surface.
178
- // ============================================================================
179
- export const pricingRulesEditor = example({
180
- keywords: ["Diff", "side-by-side", "Slider", "Input", "pricing", "discount", "mixed"],
181
- description: "Pricing rules editor — sliders for list price/discount, IntegerInput for min order qty, StringInput for currency; Diff in side-by-side mode",
182
- fn: East.function([], UIComponentType, (_$) => {
183
- return (_jsx(Reactive, { children: $ => {
184
- const listPrice = $.let(Data.bind(listPriceInput, { mode: "staged" }));
185
- const discountPct = $.let(Data.bind(discountPctInput, { mode: "staged" }));
186
- const minOrderQty = $.let(Data.bind(minOrderQtyInput, { mode: "staged" }));
187
- const currency = $.let(Data.bind(currencyCodeInput, { mode: "staged" }));
188
- return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Pricing rules" }), _jsx(Text, { children: "Stage pricing changes \u2014 review side-by-side before applying to the catalog." }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "List price" }), _jsx(Slider, { value: listPrice.read(), min: 0.0, max: 999.95, step: 0.05, onChangeEnd: ($, v) => $(listPrice.write(v)) })] }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "Discount (%)" }), _jsx(Slider, { value: discountPct.read(), min: 0.0, max: 75.0, step: 0.5, onChangeEnd: ($, v) => $(discountPct.write(v)) })] }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "Minimum order quantity" }), _jsx(Input.Integer, { value: minOrderQty.read(), min: 1n, max: 1000n, onChange: ($, v) => $(minOrderQty.write(v)) })] }), _jsxs(VStack, { gap: "1", children: [_jsx(Text, { textStyle: "label-sm", children: "Currency code" }), _jsx(Input.String, { value: currency.read(), placeholder: "AUD", onChange: ($, v) => $(currency.write(v)) })] }), _jsx(Diff, { bindings: [listPrice.binding, discountPct.binding, minOrderQty.binding, currency.binding], hideUnchanged: some(true) })] }) }));
189
- } }));
190
- }),
191
- inputs: [],
192
- });
193
- // ============================================================================
194
- // 5. Feature flags editor — Set<String> binding; Switch per known flag.
195
- // Demonstrates Set insert/delete patches in the Diff.
196
- // ============================================================================
197
- export const featureFlagsEditor = example({
198
- keywords: ["Diff", "Set", "Switch", "feature flags", "bindStaged"],
199
- description: "Feature-flags editor — Switch per known flag toggles inclusion in a staged Set; Diff shows insertions / deletions",
200
- fn: East.function([], UIComponentType, (_$) => {
201
- return (_jsx(Reactive, { children: $ => {
202
- const flags = $.let(Data.bind(featureFlagsInput, { mode: "staged" }));
203
- const flagsRead = $.let(flags.read(), SetType(StringType));
204
- // ONE East closure factory: `toggle(flag)` returns the per-switch
205
- // handler as a real East function value (captures `flag` in East).
206
- const toggle = $.const(East.function([StringType], FunctionType([BooleanType], NullType), (_$, flag) => East.function([BooleanType], NullType, ($, isOn) => {
207
- const next = $.let(flags.read(), SetType(StringType));
208
- $.if(isOn, $ => { $(next.insert(flag)); }).else($ => { $(next.delete(flag)); });
209
- $(flags.write(next));
210
- })));
211
- const onDarkMode = $.const(toggle("dark_mode"));
212
- const onExperiments = $.const(toggle("experiments"));
213
- const onNotifications = $.const(toggle("notifications"));
214
- const onAnalytics = $.const(toggle("analytics"));
215
- const onAiAssist = $.const(toggle("ai_assist"));
216
- return (_jsx(Card, { children: _jsxs(VStack, { gap: "4", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Feature flags" }), _jsx(Text, { children: "Toggle flags to stage changes; Diff card below shows the set delta." }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "dark_mode" }), _jsx(Switch, { checked: flagsRead.has("dark_mode"), onChange: onDarkMode })] }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "experiments" }), _jsx(Switch, { checked: flagsRead.has("experiments"), onChange: onExperiments })] }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "notifications" }), _jsx(Switch, { checked: flagsRead.has("notifications"), onChange: onNotifications })] }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "analytics" }), _jsx(Switch, { checked: flagsRead.has("analytics"), onChange: onAnalytics })] }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "ai_assist" }), _jsx(Switch, { checked: flagsRead.has("ai_assist"), onChange: onAiAssist })] }), _jsx(Diff, { bindings: [flags.binding], hideUnchanged: some(true) })] }) }));
217
- } }));
218
- }),
219
- inputs: [],
220
- });
221
- // ============================================================================
222
- // 6. Regional pricing editor — Dict<String, Float>; Input per known key.
223
- // Demonstrates Dict update patches per key in the Diff.
224
- // ============================================================================
225
- export const regionalPricingEditor = example({
226
- keywords: ["Diff", "Dict", "Input", "regional pricing", "bindStaged"],
227
- description: "Regional-pricing editor — Input.Float per region writes back to a staged Dict; Diff shows per-key updates",
228
- fn: East.function([], UIComponentType, (_$) => {
229
- return (_jsx(Reactive, { children: $ => {
230
- const prices = $.let(Data.bind(regionalPricesInput, { mode: "staged" }));
231
- const pricesRead = $.let(prices.read(), DictType(StringType, FloatType));
232
- // ONE East closure factory: `setPrice(region)` returns the
233
- // per-region handler as a real East function value.
234
- const setPrice = $.const(East.function([StringType], FunctionType([FloatType], NullType), (_$, region) => East.function([FloatType], NullType, ($, newPrice) => {
235
- const next = $.let(prices.read(), DictType(StringType, FloatType));
236
- $(next.insertOrUpdate(region, newPrice));
237
- $(prices.write(next));
238
- })));
239
- const onAu = $.const(setPrice("AU"));
240
- const onUs = $.const(setPrice("US"));
241
- const onEu = $.const(setPrice("EU"));
242
- const onJp = $.const(setPrice("JP"));
243
- return (_jsx(Card, { children: _jsxs(VStack, { gap: "4", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Regional pricing" }), _jsx(Text, { children: "Edit per-region prices; Diff card below tracks pending updates." }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "AU" }), _jsx(Input.Float, { value: pricesRead.get("AU", East.function([StringType], FloatType, _$ => 0.0)), min: 0.0, max: 99999.0, step: 0.05, onChange: onAu })] }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "US" }), _jsx(Input.Float, { value: pricesRead.get("US", East.function([StringType], FloatType, _$ => 0.0)), min: 0.0, max: 99999.0, step: 0.05, onChange: onUs })] }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "EU" }), _jsx(Input.Float, { value: pricesRead.get("EU", East.function([StringType], FloatType, _$ => 0.0)), min: 0.0, max: 99999.0, step: 0.05, onChange: onEu })] }), _jsxs(VStack, { gap: "3", justify: "space-between", children: [_jsx(Text, { textStyle: "label-sm", children: "JP" }), _jsx(Input.Float, { value: pricesRead.get("JP", East.function([StringType], FloatType, _$ => 0.0)), min: 0.0, max: 99999.0, step: 0.05, onChange: onJp })] }), _jsx(Diff, { bindings: [prices.binding], hideUnchanged: some(true) })] }) }));
244
- } }));
245
- }),
246
- inputs: [],
247
- });
248
- // ============================================================================
249
- // 7. Deployment status editor — Variant binding; one Button per status.
250
- // Demonstrates Variant tag changes in the Diff.
251
- // ============================================================================
252
- export const deploymentStatusEditor = example({
253
- keywords: ["Diff", "Variant", "Button", "deployment status", "bindStaged"],
254
- description: "Deployment-status editor — buttons set a Variant binding; Diff shows the status tag change",
255
- fn: East.function([], UIComponentType, (_$) => {
256
- return (_jsx(Reactive, { children: $ => {
257
- const status = $.let(Data.bind(deploymentStatusInput, { mode: "staged" }));
258
- const statusRead = $.let(status.read(), DeploymentStatusType);
259
- const setPending = $.const(East.function([], NullType, $ => $(status.write(variant("pending", null)))));
260
- const setInProgress = $.const(East.function([], NullType, $ => $(status.write(variant("in_progress", null)))));
261
- const setComplete = $.const(East.function([], NullType, $ => $(status.write(variant("complete", null)))));
262
- const setFailed = $.const(East.function([], NullType, $ => $(status.write(variant("failed", null)))));
263
- return (_jsx(Card, { children: _jsxs(VStack, { gap: "4", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Deployment status" }), _jsx(Text, { children: "Current:" }), _jsx(Text, { textStyle: "label-md", children: statusRead.getTag() }), _jsxs(HStack, { gap: "2", children: [_jsx(Button, { onClick: setPending, children: "Pending" }), _jsx(Button, { onClick: setInProgress, children: "In progress" }), _jsx(Button, { onClick: setComplete, children: "Complete" }), _jsx(Button, { onClick: setFailed, children: "Failed" })] }), _jsx(Diff, { bindings: [status.binding], hideUnchanged: some(true) })] }) }));
264
- } }));
265
- }),
266
- inputs: [],
267
- });
268
- // ============================================================================
269
- // 8. Minimal call site — defaults only (used by IR-roundtrip + smoke tests)
238
+ // 4. Minimal call site defaults only (used by IR-roundtrip + smoke tests)
270
239
  // ============================================================================
271
240
  export const diffDefaults = example({
272
241
  keywords: ["Diff", "Root", "defaults", "minimal"],
@@ -318,50 +287,6 @@ export const mergeConflictDemo = example({
318
287
  inputs: [],
319
288
  });
320
289
  // ============================================================================
321
- // Density variants — same pricing-rules content rendered at the two
322
- // non-default density presets, so the showcase can compare side-by-side
323
- // against the default (`pricingRulesEditor` above).
324
- // ============================================================================
325
- /**
326
- * Pricing-rules editor at `compact` density — tighter row padding and smaller
327
- * type scale than the default `comfortable`. Suited to data-dense pages where
328
- * the Diff card is one of several panels competing for vertical space.
329
- */
330
- export const pricingRulesEditorCompact = example({
331
- keywords: ["Diff", "density", "compact", "Slider", "Input", "pricing"],
332
- description: "Pricing-rules editor with `density: \"compact\"` — same content as pricingRulesEditor, denser rows",
333
- fn: East.function([], UIComponentType, (_$) => {
334
- return (_jsx(Reactive, { children: $ => {
335
- const listPrice = $.let(Data.bind(listPriceInput, { mode: "staged" }));
336
- const discountPct = $.let(Data.bind(discountPctInput, { mode: "staged" }));
337
- const minOrderQty = $.let(Data.bind(minOrderQtyInput, { mode: "staged" }));
338
- const currency = $.let(Data.bind(currencyCodeInput, { mode: "staged" }));
339
- return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Pricing rules \u2014 compact" }), _jsx(Slider, { value: listPrice.read(), min: 0.0, max: 999.95, step: 0.05, onChangeEnd: ($, v) => $(listPrice.write(v)) }), _jsx(Slider, { value: discountPct.read(), min: 0.0, max: 75.0, step: 0.5, onChangeEnd: ($, v) => $(discountPct.write(v)) }), _jsx(Input.Integer, { value: minOrderQty.read(), min: 1n, max: 1000n, onChange: ($, v) => $(minOrderQty.write(v)) }), _jsx(Input.String, { value: currency.read(), placeholder: "AUD", onChange: ($, v) => $(currency.write(v)) }), _jsx(Diff, { bindings: [listPrice.binding, discountPct.binding, minOrderQty.binding, currency.binding], density: "compact", hideUnchanged: some(true) })] }) }));
340
- } }));
341
- }),
342
- inputs: [],
343
- });
344
- /**
345
- * Pricing-rules editor at `condensed` density — mission-control sizing.
346
- * Tightest row padding and smallest type scale; pairs with status dashboards
347
- * and other read-heavy contexts where a diff list is reference data, not the
348
- * main interaction surface.
349
- */
350
- export const pricingRulesEditorCondensed = example({
351
- keywords: ["Diff", "density", "condensed", "Slider", "Input", "pricing"],
352
- description: "Pricing-rules editor with `density: \"condensed\"` — mission-control sizing for read-heavy views",
353
- fn: East.function([], UIComponentType, (_$) => {
354
- return (_jsx(Reactive, { children: $ => {
355
- const listPrice = $.let(Data.bind(listPriceInput, { mode: "staged" }));
356
- const discountPct = $.let(Data.bind(discountPctInput, { mode: "staged" }));
357
- const minOrderQty = $.let(Data.bind(minOrderQtyInput, { mode: "staged" }));
358
- const currency = $.let(Data.bind(currencyCodeInput, { mode: "staged" }));
359
- return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Pricing rules \u2014 condensed" }), _jsx(Slider, { value: listPrice.read(), min: 0.0, max: 999.95, step: 0.05, onChangeEnd: ($, v) => $(listPrice.write(v)) }), _jsx(Slider, { value: discountPct.read(), min: 0.0, max: 75.0, step: 0.5, onChangeEnd: ($, v) => $(discountPct.write(v)) }), _jsx(Input.Integer, { value: minOrderQty.read(), min: 1n, max: 1000n, onChange: ($, v) => $(minOrderQty.write(v)) }), _jsx(Input.String, { value: currency.read(), placeholder: "AUD", onChange: ($, v) => $(currency.write(v)) }), _jsx(Diff, { bindings: [listPrice.binding, discountPct.binding, minOrderQty.binding, currency.binding], density: "condensed", hideUnchanged: some(true) })] }) }));
360
- } }));
361
- }),
362
- inputs: [],
363
- });
364
- // ============================================================================
365
290
  // Overlay-mode bindings — patches stored in a sibling `e3.input` typed
366
291
  // `PatchType(T)`. The Diff component surfaces them via the `overlay` option
367
292
  // instead of `staged`. See `Data.bindOverlay`.
@@ -372,9 +297,9 @@ export const regionalPricesPatchInput = e3.input("regional_prices_patch", PatchT
372
297
  export const rosterPatchInput = e3.input("roster_patch", PatchType(RosterArrayType), variant("unchanged", null));
373
298
  // Drift-laden patch input — defaults to a non-trivial patch whose ops are
374
299
  // stale relative to the source dict `{AU: 49.95, US: 39.95, EU: 44.95, JP:
375
- // 5499.0}`. Used by `regionalPricingOverlayDrift` to demonstrate what the
376
- // Diff card surfaces when a server-stored patch was authored against an
377
- // older version of its source. Conflicts (per `apply.ts` semantics):
300
+ // 5499.0}`. Used by `diffOverlayVariants` (the REGIONAL PRICING OVERLAY
301
+ // DRIFT row) to demonstrate what the Diff card surfaces when a server-stored
302
+ // patch was authored against an older version of its source. Conflicts (per `apply.ts` semantics):
378
303
  // - `delete "MX"` — key not in source → stale delete
379
304
  // - `insert "AU"` — key already exists in source → stale insert
380
305
  // - `update "US"` with `replace(before=30 → 25)` — before mismatches source's 39.95
@@ -403,108 +328,75 @@ const rosterDriftEdited = [
403
328
  ];
404
329
  export const rosterDriftPatchInput = e3.input("roster_drift_patch", PatchType(RosterArrayType), diffFor(RosterArrayType)(rosterDriftBase, rosterDriftEdited));
405
330
  /**
406
- * Single-Float overlay editor Slider edits go to `max_weekly_hours_patch`,
407
- * the Diff card surfaces the patch against the source.
408
- */
409
- export const policyOverlayEditor = example({
410
- keywords: ["Diff", "bindOverlay", "Slider", "overlay", "policy", "patch"],
411
- description: "Overlay-mode editor Slider writes patches to a sibling e3.input; Diff shows them",
412
- fn: East.function([], UIComponentType, (_$) => {
413
- return (_jsx(Reactive, { children: $ => {
414
- const view = $.let(Data.bind(maxWeeklyHoursInput, { mode: "direct", patch: maxWeeklyHoursPatchInput }));
415
- return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Max weekly hours (overlay)" }), _jsx(Slider, { value: view.read(), min: 30.0, max: 60.0, step: 1.0, onChangeEnd: ($, v) => $(view.write(v)) }), _jsx(Diff, { bindings: [view.binding], hideUnchanged: some(true) })] }) }));
416
- } }));
417
- }),
418
- inputs: [],
419
- });
420
- /**
421
- * Overlay binding whose patch input *starts* with a non-trivial patch that
422
- * is stale relative to the source. Demonstrates what the Diff card displays
423
- * when a server-stored patch was authored against an older revision of its
424
- * source — stale delete, stale insert, stale replace.
425
- *
426
- * No form components: `view.read()` calls `apply(source, patch)`, which
427
- * throws `ConflictError` on the stale ops. The Diff card walks the patch IR
428
- * directly from cache bytes (no apply) so it renders cleanly. The
429
- * `bindOverlay` call is kept so the renderer's overlay-type registry knows
430
- * how to decode the patch bytes for this binding.
331
+ * Overlay-mode variant panel. POLICY OVERLAY: Slider edits go to
332
+ * `max_weekly_hours_patch`, the Diff card surfaces the patch against the
333
+ * source. REGIONAL PRICING OVERLAY DRIFT: the patch input *starts* with a
334
+ * non-trivial patch that is stale relative to the source — what the Diff card
335
+ * displays when a server-stored patch was authored against an older revision
336
+ * (stale delete, stale insert, stale replace); no form components, because
337
+ * `view.read()` calls `apply(source, patch)` which throws `ConflictError` on
338
+ * the stale ops, while the Diff card walks the patch IR directly from cache
339
+ * bytes (no apply) so it renders cleanly (the bind is kept so the renderer's
340
+ * overlay-type registry knows how to decode the patch bytes). ROSTER OVERLAY
341
+ * DRIFT: an array-of-structs patch exercising nested grouping (binding →
342
+ * `[index]` → struct field) — only `rate` of entries 0 and 1 change, so the
343
+ * card renders `ROSTER → [0] → rate`, `[1] → rate`. ROSTER TABLE OVERLAY:
344
+ * the roster table editor with patches stored in `roster_patch`, surviving
345
+ * page reload and visible to other workspace sessions.
431
346
  */
432
- export const regionalPricingOverlayDrift = example({
433
- keywords: ["Diff", "bindOverlay", "Dict", "conflict", "drift", "patch"],
434
- description: "Overlay-mode example with a stale patch — Diff card surfaces ops that don't match the source",
347
+ export const diffOverlayVariants = example({
348
+ keywords: ["Diff", "bindOverlay", "Slider", "overlay", "policy", "patch", "Dict", "conflict", "drift", "roster", "array", "nested", "Table"],
349
+ description: "Overlay variant panel — POLICY OVERLAY: Slider writes patches to a sibling e3.input, Diff shows them; REGIONAL PRICING OVERLAY DRIFT: a stale patch — the Diff card surfaces ops that don't match the source; ROSTER OVERLAY DRIFT: an overlay roster patch — the Diff card surfaces nested array-element field changes; ROSTER TABLE OVERLAY: an editable table backed by a separate patch e3.input — patches persist across sessions",
435
350
  fn: East.function([], UIComponentType, (_$) => {
436
- return (_jsx(Reactive, { children: $ => {
437
- const view = $.let(Data.bind(regionalPricesInput, { mode: "direct", patch: regionalPricesDriftPatchInput }));
438
- return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Regional pricing \u2014 overlay with stale patch" }), _jsx(Text, { children: "The patch input was authored against an older source. The Diff card below "
439
- + "shows: a stale delete (MX missing from source), a stale insert (AU already "
440
- + "exists), a stale replace (US before=30 doesn't match current 39.95), and "
441
- + "one clean replace (EU 44.95 39.95). Apply would throw ConflictError on "
442
- + "the stale ops; this example exists to show what the Diff renderer surfaces "
443
- + "when a server-stored patch has drifted from its source." }), _jsx(Diff, { bindings: [view.binding], hideUnchanged: some(true) })] }) }));
444
- } }));
445
- }),
446
- inputs: [],
447
- });
448
- /**
449
- * Roster overlay drift array-of-structs patch surfaced by the Diff card,
450
- * exercising nested grouping (binding `[index]` struct field). The patch
451
- * touches only `rate` on the first two entries, so the card renders
452
- * `ROSTER [0] rate`, `[1] rate`.
453
- */
454
- export const rosterOverlayDrift = example({
455
- keywords: ["Diff", "overlay", "roster", "array", "nested", "patch"],
456
- description: "Overlay-mode roster patch — Diff card surfaces nested array-element field changes",
457
- fn: East.function([], UIComponentType, (_$) => {
458
- return (_jsx(Reactive, { children: $ => {
459
- const view = $.let(Data.bind(rosterInput, { mode: "direct", patch: rosterDriftPatchInput }));
460
- return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Roster \u2014 overlay patch (nested)" }), _jsx(Text, { children: "The patch changes the hourly rate of the first two roster entries. The "
461
- + "Diff card groups each change under its array index, demonstrating the "
462
- + "binding [index] → field nesting." }), _jsx(Diff, { bindings: [view.binding], hideUnchanged: some(true) })] }) }));
463
- } }));
464
- }),
465
- inputs: [],
466
- });
467
- /**
468
- * Roster table editor in overlay mode — patches stored in `roster_patch`,
469
- * survive page reload and are visible to other workspace sessions.
470
- */
471
- export const rosterTableEditorOverlay = example({
472
- keywords: ["Diff", "Table", "bindOverlay", "patch", "overlay", "roster"],
473
- description: "Editable table backed by a separate patch e3.input — patches persist across sessions",
474
- fn: East.function([], UIComponentType, (_$) => {
475
- return (_jsx(Reactive, { children: $ => {
476
- const view = $.let(Data.bind(rosterInput, { mode: "direct", patch: rosterPatchInput }));
477
- const rosterArray = $.let(view.read(), RosterArrayType);
478
- return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Worker roster (overlay-mode)" }), _jsx(Text, { children: "Patches stored in a sibling dataset \u2014 survive reload, visible to other sessions." }), _jsx(Table, { data: rosterArray, columns: {
479
- name: { header: "Name" },
480
- rate: {
481
- header: "Hourly rate ($)",
482
- render: East.function([Table.Types.CellRenderContext], UIComponentType, ($, ctx) => {
483
- const idx = $.let(ctx.rowIndex, IntegerType);
484
- const row = $.let(rosterArray.get(idx), RosterEntryType);
485
- const onRateChange = $.const(East.function([FloatType], NullType, ($, v) => {
486
- const fresh = $.let(view.read(), RosterArrayType);
487
- const next = $.let(fresh.map(($, r, i) => i.equal(idx).ifElse(_$ => ({ ...r, rate: v }), _$ => r)), RosterArrayType);
488
- $(view.write(next));
489
- }));
490
- return (_jsx(Input.Float, { value: row.rate, min: 15.0, max: 80.0, step: 0.25, onChange: onRateChange }));
491
- }),
492
- },
493
- shiftLength: {
494
- header: "Shift length (h)",
495
- render: East.function([Table.Types.CellRenderContext], UIComponentType, ($, ctx) => {
496
- const idx = $.let(ctx.rowIndex, IntegerType);
497
- const row = $.let(rosterArray.get(idx), RosterEntryType);
498
- const onShiftChange = $.const(East.function([IntegerType], NullType, ($, v) => {
499
- const fresh = $.let(view.read(), RosterArrayType);
500
- const next = $.let(fresh.map(($, r, i) => i.equal(idx).ifElse(_$ => ({ ...r, shiftLength: v }), _$ => r)), RosterArrayType);
501
- $(view.write(next));
502
- }));
503
- return (_jsx(Input.Integer, { value: row.shiftLength, min: 4n, max: 12n, onChange: onShiftChange }));
504
- }),
505
- },
506
- }, variant: "line", striped: true }), _jsx(Diff, { bindings: [view.binding], hideUnchanged: some(true) })] }) }));
507
- } }));
351
+ return (_jsxs(VStack, { gap: "4", align: "stretch", children: [_jsx(Separator, { label: "POLICY OVERLAY", align: "start" }), _jsx(Reactive, { children: $ => {
352
+ const view = $.let(Data.bind(maxWeeklyHoursInput, { mode: "direct", patch: maxWeeklyHoursPatchInput }));
353
+ return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Max weekly hours (overlay)" }), _jsx(Slider, { value: view.read(), min: 30.0, max: 60.0, step: 1.0, onChangeEnd: ($, v) => $(view.write(v)) }), _jsx(Diff, { bindings: [view.binding], hideUnchanged: some(true) })] }) }));
354
+ } }), _jsx(Separator, { label: "REGIONAL PRICING OVERLAY DRIFT", align: "start" }), _jsx(Reactive, { children: $ => {
355
+ const view = $.let(Data.bind(regionalPricesInput, { mode: "direct", patch: regionalPricesDriftPatchInput }));
356
+ return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Regional pricing \u2014 overlay with stale patch" }), _jsx(Text, { children: "The patch input was authored against an older source. The Diff card below "
357
+ + "shows: a stale delete (MX missing from source), a stale insert (AU already "
358
+ + "exists), a stale replace (US before=30 doesn't match current 39.95), and "
359
+ + "one clean replace (EU 44.95 → 39.95). Apply would throw ConflictError on "
360
+ + "the stale ops; this example exists to show what the Diff renderer surfaces "
361
+ + "when a server-stored patch has drifted from its source." }), _jsx(Diff, { bindings: [view.binding], hideUnchanged: some(true) })] }) }));
362
+ } }), _jsx(Separator, { label: "ROSTER OVERLAY DRIFT", align: "start" }), _jsx(Reactive, { children: $ => {
363
+ const view = $.let(Data.bind(rosterInput, { mode: "direct", patch: rosterDriftPatchInput }));
364
+ return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Roster \u2014 overlay patch (nested)" }), _jsx(Text, { children: "The patch changes the hourly rate of the first two roster entries. The "
365
+ + "Diff card groups each change under its array index, demonstrating the "
366
+ + "binding [index] field nesting." }), _jsx(Diff, { bindings: [view.binding], hideUnchanged: some(true) })] }) }));
367
+ } }), _jsx(Separator, { label: "ROSTER TABLE OVERLAY", align: "start" }), _jsx(Reactive, { children: $ => {
368
+ const view = $.let(Data.bind(rosterInput, { mode: "direct", patch: rosterPatchInput }));
369
+ const rosterArray = $.let(view.read(), RosterArrayType);
370
+ return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Worker roster (overlay-mode)" }), _jsx(Text, { children: "Patches stored in a sibling dataset \u2014 survive reload, visible to other sessions." }), _jsx(Table, { data: rosterArray, columns: {
371
+ name: { header: "Name" },
372
+ rate: {
373
+ header: "Hourly rate ($)",
374
+ render: East.function([Table.Types.CellRenderContext], UIComponentType, ($, ctx) => {
375
+ const idx = $.let(ctx.rowIndex, IntegerType);
376
+ const row = $.let(rosterArray.get(idx), RosterEntryType);
377
+ const onRateChange = $.const(East.function([FloatType], NullType, ($, v) => {
378
+ const fresh = $.let(view.read(), RosterArrayType);
379
+ const next = $.let(fresh.map(($, r, i) => i.equal(idx).ifElse(_$ => ({ ...r, rate: v }), _$ => r)), RosterArrayType);
380
+ $(view.write(next));
381
+ }));
382
+ return (_jsx(Input.Float, { value: row.rate, min: 15.0, max: 80.0, step: 0.25, onChange: onRateChange }));
383
+ }),
384
+ },
385
+ shiftLength: {
386
+ header: "Shift length (h)",
387
+ render: East.function([Table.Types.CellRenderContext], UIComponentType, ($, ctx) => {
388
+ const idx = $.let(ctx.rowIndex, IntegerType);
389
+ const row = $.let(rosterArray.get(idx), RosterEntryType);
390
+ const onShiftChange = $.const(East.function([IntegerType], NullType, ($, v) => {
391
+ const fresh = $.let(view.read(), RosterArrayType);
392
+ const next = $.let(fresh.map(($, r, i) => i.equal(idx).ifElse(_$ => ({ ...r, shiftLength: v }), _$ => r)), RosterArrayType);
393
+ $(view.write(next));
394
+ }));
395
+ return (_jsx(Input.Integer, { value: row.shiftLength, min: 4n, max: 12n, onChange: onShiftChange }));
396
+ }),
397
+ },
398
+ }, variant: "line", striped: true }), _jsx(Diff, { bindings: [view.binding], hideUnchanged: some(true) })] }) }));
399
+ } })] }));
508
400
  }),
509
401
  inputs: [],
510
402
  });
@@ -516,62 +408,53 @@ export const rosterTableEditorOverlay = example({
516
408
  // the unit of review.
517
409
  // ============================================================================
518
410
  /**
519
- * Single-Float staged-with-patch editor buffered Slider edits publish to
520
- * `max_weekly_hours_patch` on Apply. The source `max_weekly_hours` stays
521
- * untouched until a separate apply-patch-to-source step.
522
- */
523
- export const policyStagedPatchEditor = example({
524
- keywords: ["Diff", "Slider", "staged", "patch", "publish", "policy"],
525
- description: "Slider edits buffered locally; Apply publishes draft to a server-backed patch dataset",
526
- fn: East.function([], UIComponentType, (_$) => {
527
- return (_jsx(Reactive, { children: $ => {
528
- const view = $.let(Data.bind(maxWeeklyHoursInput, { mode: "staged", patch: maxWeeklyHoursPatchInput }));
529
- return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Max weekly hours (staged + patch)" }), _jsx(Text, { children: "Drag to buffer locally; Apply publishes the draft as a patch to the patch dataset (source untouched)." }), _jsx(Slider, { value: view.read(), min: 30.0, max: 60.0, step: 1.0, onChange: ($, v) => $(view.write(v)) }), _jsx(Diff, { bindings: [view.binding], hideUnchanged: some(true) })] }) }));
530
- } }));
531
- }),
532
- inputs: [],
533
- });
534
- /**
535
- * Roster table editor in staged + patch mode. Cell edits buffer in
536
- * IndexedDB until Apply, which publishes a fresh patch to `roster_patch`.
537
- * Survives reload as a draft; multi-session reviewers see the patch only
411
+ * Staged + patch variant panel. POLICY STAGED PATCH: single-Float
412
+ * staged-with-patch editor buffered Slider edits publish to
413
+ * `max_weekly_hours_patch` on Apply; the source `max_weekly_hours` stays
414
+ * untouched until a separate apply-patch-to-source step. ROSTER STAGED
415
+ * PATCH: the roster table editor in staged + patch mode — cell edits buffer
416
+ * in IndexedDB until Apply, which publishes a fresh patch to `roster_patch`;
417
+ * survives reload as a draft, and multi-session reviewers see the patch only
538
418
  * after the author commits.
539
419
  */
540
- export const rosterStagedPatchEditor = example({
541
- keywords: ["Diff", "Table", "staged", "patch", "publish", "roster"],
542
- description: "Editable roster — edits buffered locally; Apply publishes a fresh patch to a server-backed patch dataset",
420
+ export const diffStagedPatchVariants = example({
421
+ keywords: ["Diff", "Slider", "staged", "patch", "publish", "policy", "Table", "roster"],
422
+ description: "Staged + patch variant panel POLICY STAGED PATCH: Slider edits buffered locally, Apply publishes the draft to a server-backed patch dataset; ROSTER STAGED PATCH: an editable roster whose buffered cell edits publish a fresh patch to the patch dataset on Apply",
543
423
  fn: East.function([], UIComponentType, (_$) => {
544
- return (_jsx(Reactive, { children: $ => {
545
- const view = $.let(Data.bind(rosterInput, { mode: "staged", patch: rosterPatchInput }));
546
- const rosterArray = $.let(view.read(), RosterArrayType);
547
- return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Worker roster (staged + patch)" }), _jsx(Text, { children: "Edits buffer locally until Apply, which publishes a draft patch to the patch dataset for review." }), _jsx(Table, { data: rosterArray, columns: {
548
- name: { header: "Name" },
549
- rate: {
550
- header: "Hourly rate ($)",
551
- render: East.function([Table.Types.CellRenderContext], UIComponentType, ($, ctx) => {
552
- const idx = $.let(ctx.rowIndex, IntegerType);
553
- const row = $.let(rosterArray.get(idx), RosterEntryType);
554
- const onRateChange = $.const(East.function([FloatType], NullType, ($, v) => {
555
- const fresh = $.let(view.read(), RosterArrayType);
556
- $(view.write(fresh.map(($, r, i) => i.equal(idx).ifElse(_$ => ({ ...r, rate: v }), () => r))));
557
- }));
558
- return (_jsx(Input.Float, { value: row.rate, min: 15.0, max: 80.0, step: 0.25, onChange: onRateChange }));
559
- }),
560
- },
561
- shiftLength: {
562
- header: "Shift length (h)",
563
- render: East.function([Table.Types.CellRenderContext], UIComponentType, ($, ctx) => {
564
- const idx = $.let(ctx.rowIndex, IntegerType);
565
- const row = $.let(rosterArray.get(idx), RosterEntryType);
566
- const onShiftChange = $.const(East.function([IntegerType], NullType, ($, v) => {
567
- const fresh = $.let(view.read(), RosterArrayType);
568
- $(view.write(fresh.map(($, r, i) => i.equal(idx).ifElse(_$ => ({ ...r, shiftLength: v }), () => r))));
569
- }));
570
- return (_jsx(Input.Integer, { value: row.shiftLength, min: 4n, max: 12n, onChange: onShiftChange }));
571
- }),
572
- },
573
- }, variant: "line", striped: true }), _jsx(Diff, { bindings: [view.binding], hideUnchanged: some(true) })] }) }));
574
- } }));
424
+ return (_jsxs(VStack, { gap: "4", align: "stretch", children: [_jsx(Separator, { label: "POLICY STAGED PATCH", align: "start" }), _jsx(Reactive, { children: $ => {
425
+ const view = $.let(Data.bind(maxWeeklyHoursInput, { mode: "staged", patch: maxWeeklyHoursPatchInput }));
426
+ return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Max weekly hours (staged + patch)" }), _jsx(Text, { children: "Drag to buffer locally; Apply publishes the draft as a patch to the patch dataset (source untouched)." }), _jsx(Slider, { value: view.read(), min: 30.0, max: 60.0, step: 1.0, onChange: ($, v) => $(view.write(v)) }), _jsx(Diff, { bindings: [view.binding], hideUnchanged: some(true) })] }) }));
427
+ } }), _jsx(Separator, { label: "ROSTER STAGED PATCH", align: "start" }), _jsx(Reactive, { children: $ => {
428
+ const view = $.let(Data.bind(rosterInput, { mode: "staged", patch: rosterPatchInput }));
429
+ const rosterArray = $.let(view.read(), RosterArrayType);
430
+ return (_jsx(Card, { children: _jsxs(VStack, { gap: "5", align: "stretch", children: [_jsx(Text, { textStyle: "heading-md", children: "Worker roster (staged + patch)" }), _jsx(Text, { children: "Edits buffer locally until Apply, which publishes a draft patch to the patch dataset for review." }), _jsx(Table, { data: rosterArray, columns: {
431
+ name: { header: "Name" },
432
+ rate: {
433
+ header: "Hourly rate ($)",
434
+ render: East.function([Table.Types.CellRenderContext], UIComponentType, ($, ctx) => {
435
+ const idx = $.let(ctx.rowIndex, IntegerType);
436
+ const row = $.let(rosterArray.get(idx), RosterEntryType);
437
+ const onRateChange = $.const(East.function([FloatType], NullType, ($, v) => {
438
+ const fresh = $.let(view.read(), RosterArrayType);
439
+ $(view.write(fresh.map(($, r, i) => i.equal(idx).ifElse(_$ => ({ ...r, rate: v }), () => r))));
440
+ }));
441
+ return (_jsx(Input.Float, { value: row.rate, min: 15.0, max: 80.0, step: 0.25, onChange: onRateChange }));
442
+ }),
443
+ },
444
+ shiftLength: {
445
+ header: "Shift length (h)",
446
+ render: East.function([Table.Types.CellRenderContext], UIComponentType, ($, ctx) => {
447
+ const idx = $.let(ctx.rowIndex, IntegerType);
448
+ const row = $.let(rosterArray.get(idx), RosterEntryType);
449
+ const onShiftChange = $.const(East.function([IntegerType], NullType, ($, v) => {
450
+ const fresh = $.let(view.read(), RosterArrayType);
451
+ $(view.write(fresh.map(($, r, i) => i.equal(idx).ifElse(_$ => ({ ...r, shiftLength: v }), () => r))));
452
+ }));
453
+ return (_jsx(Input.Integer, { value: row.shiftLength, min: 4n, max: 12n, onChange: onShiftChange }));
454
+ }),
455
+ },
456
+ }, variant: "line", striped: true }), _jsx(Diff, { bindings: [view.binding], hideUnchanged: some(true) })] }) }));
457
+ } })] }));
575
458
  }),
576
459
  inputs: [],
577
460
  });