@petrarca/sonnet-playground 0.5.0 → 0.6.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.
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  PlayCoreComponents
3
- } from "./chunk-Q6NLY2BZ.js";
3
+ } from "./chunk-6WI3N7JI.js";
4
4
  import "./chunk-C2EZ2ECG.js";
5
5
  export {
6
6
  PlayCoreComponents as default
7
7
  };
8
- //# sourceMappingURL=PlayCoreComponents-AG5D4SBS.js.map
8
+ //# sourceMappingURL=PlayCoreComponents-YTEAS3GL.js.map
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  PlayFormWidgets
3
- } from "./chunk-DZB6WFHA.js";
3
+ } from "./chunk-UB7462QG.js";
4
4
  import "./chunk-C2EZ2ECG.js";
5
5
  export {
6
6
  PlayFormWidgets as default
7
7
  };
8
- //# sourceMappingURL=PlayFormWidgets-IWJJQ5XL.js.map
8
+ //# sourceMappingURL=PlayFormWidgets-6JYFRTAL.js.map
@@ -0,0 +1,7 @@
1
+ import {
2
+ PlayForms
3
+ } from "./chunk-ZSUCFEB6.js";
4
+ export {
5
+ PlayForms as default
6
+ };
7
+ //# sourceMappingURL=PlayForms-2G7PROCH.js.map
@@ -0,0 +1,7 @@
1
+ import {
2
+ PlaySchemaDesigner
3
+ } from "./chunk-6VQJFBTM.js";
4
+ export {
5
+ PlaySchemaDesigner as default
6
+ };
7
+ //# sourceMappingURL=PlaySchemaDesigner-ZM4F7KBU.js.map
@@ -86,6 +86,131 @@ var AUDIT_SCHEMA = {
86
86
  }
87
87
  }
88
88
  };
89
+ var LOGIC_SCHEMA = {
90
+ title: "Checkout",
91
+ type: "object",
92
+ // A reusable definition referenced by $ref (shows read-only expansion).
93
+ $defs: {
94
+ Address: {
95
+ type: "object",
96
+ properties: {
97
+ street: { type: "string", title: "Street" },
98
+ city: { type: "string", title: "City" },
99
+ zip: { type: "string", title: "ZIP" }
100
+ }
101
+ }
102
+ },
103
+ "x-ui-order": [
104
+ "schema_version",
105
+ "amount",
106
+ "requires_approval",
107
+ "currency",
108
+ "expedited",
109
+ "delivery_window",
110
+ "gift_wrap",
111
+ "gift_message",
112
+ "shipping_address",
113
+ "note",
114
+ "payment"
115
+ ],
116
+ properties: {
117
+ // A $ref to the shared Address definition (read-only in the tree).
118
+ shipping_address: { $ref: "#/$defs/Address", title: "Shipping address" },
119
+ // A fixed value carried by every document (const authoring).
120
+ schema_version: {
121
+ type: "string",
122
+ title: "Schema version",
123
+ const: "checkout/v1"
124
+ },
125
+ amount: { type: "number", title: "Amount", minimum: 0 },
126
+ currency: {
127
+ type: "string",
128
+ title: "Currency",
129
+ enum: ["EUR", "USD", "GBP"]
130
+ },
131
+ expedited: { type: "boolean", title: "Expedited" },
132
+ gift_wrap: { type: "boolean", title: "Gift wrap" },
133
+ // Declarative visibility rule (x-ui-rule): declared at its own position,
134
+ // shown only when gift_wrap is checked. Contrast with the if/then/else
135
+ // fields above, which are structurally added by their conditionals.
136
+ gift_message: {
137
+ type: "string",
138
+ title: "Gift message",
139
+ "x-ui-rule": {
140
+ effect: "show",
141
+ condition: { scope: "/gift_wrap", schema: { const: true } }
142
+ }
143
+ },
144
+ // Nullable optional (anyOf [T, null]) -- the renderer unwraps to T.
145
+ note: {
146
+ title: "Note (optional)",
147
+ anyOf: [{ type: "string" }, { type: "null" }]
148
+ },
149
+ // A discriminated union (oneOf): the payment method.
150
+ payment: {
151
+ type: "object",
152
+ title: "Payment method",
153
+ discriminator: { propertyName: "kind" },
154
+ oneOf: [
155
+ {
156
+ title: "Card",
157
+ properties: {
158
+ kind: { const: "card" },
159
+ card_number: { type: "string", title: "Card number" },
160
+ cvc: { type: "string", title: "CVC" }
161
+ }
162
+ },
163
+ {
164
+ title: "Bank transfer",
165
+ properties: {
166
+ kind: { const: "bank" },
167
+ iban: { type: "string", title: "IBAN" }
168
+ }
169
+ },
170
+ {
171
+ title: "Cash",
172
+ properties: { kind: { const: "cash" } }
173
+ }
174
+ ]
175
+ }
176
+ },
177
+ required: ["amount", "currency"],
178
+ // Conditionals (if/then/else) authored as allOf members.
179
+ allOf: [
180
+ {
181
+ // Large amounts require an approval reference.
182
+ if: {
183
+ properties: { amount: { exclusiveMinimum: 1e3 } },
184
+ required: ["amount"]
185
+ },
186
+ then: {
187
+ properties: {
188
+ requires_approval: {
189
+ type: "string",
190
+ title: "Approval reference"
191
+ }
192
+ },
193
+ required: ["requires_approval"]
194
+ }
195
+ },
196
+ {
197
+ // Expedited orders ask for a delivery window; otherwise none.
198
+ if: {
199
+ properties: { expedited: { const: true } },
200
+ required: ["expedited"]
201
+ },
202
+ then: {
203
+ properties: {
204
+ delivery_window: {
205
+ type: "string",
206
+ title: "Delivery window",
207
+ enum: ["morning", "afternoon", "evening"]
208
+ }
209
+ }
210
+ }
211
+ }
212
+ ]
213
+ };
89
214
  var AUDIT_EDITABLE_PATHS = [
90
215
  "/properties/metadata/properties",
91
216
  "/properties/actor/properties/metadata/properties",
@@ -120,11 +245,10 @@ var PROFILES = {
120
245
  schema: SAMPLE_SCHEMA,
121
246
  capabilities: { mode: "data", previews: [] }
122
247
  },
123
- readonly: {
124
- label: "Read-only",
125
- description: "Fully locked -- view only, no edit affordances.",
126
- schema: SAMPLE_SCHEMA,
127
- readOnly: true,
248
+ logic: {
249
+ label: "Logic (variants + conditionals)",
250
+ description: "Shows every logic construct: a oneOf variant, if/then/else conditionals, a const field, and a nullable optional.",
251
+ schema: LOGIC_SCHEMA,
128
252
  capabilities: { previews: ["form", "table", "json", "capabilities"] }
129
253
  }
130
254
  };
@@ -188,4 +312,4 @@ function PlaySchemaDesigner() {
188
312
  export {
189
313
  PlaySchemaDesigner
190
314
  };
191
- //# sourceMappingURL=chunk-PBT6HTKY.js.map
315
+ //# sourceMappingURL=chunk-6VQJFBTM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pages/PlaySchemaDesigner.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport {\n SchemaDesigner,\n type SchemaDesignerCapabilities,\n} from \"@petrarca/sonnet-schema-designer\";\nimport { FormSelect } from \"@petrarca/sonnet-forms\";\nimport type { JsonSchema, UISchema } from \"@petrarca/sonnet-core/schema\";\n\nconst SAMPLE_SCHEMA: JsonSchema = {\n title: \"Patient\",\n type: \"object\",\n properties: {\n first_name: { type: \"string\", title: \"First name\", minLength: 1 },\n last_name: { type: \"string\", title: \"Last name\", minLength: 1 },\n date_of_birth: { type: \"string\", format: \"date\", title: \"Date of birth\" },\n gender: {\n type: \"string\",\n title: \"Gender\",\n enum: [\"male\", \"female\", \"other\", \"unknown\"],\n },\n active: { type: \"boolean\", title: \"Active\" },\n contact: {\n type: \"object\",\n title: \"Contact\",\n properties: {\n email: { type: \"string\", format: \"email\", title: \"Email\" },\n phone: { type: \"string\", title: \"Phone\" },\n },\n required: [\"email\"],\n },\n addresses: {\n type: \"array\",\n title: \"Addresses\",\n minItems: 1,\n maxItems: 3,\n items: {\n type: \"object\",\n properties: {\n street: { type: \"string\", title: \"Street\" },\n city: { type: \"string\", title: \"City\" },\n zip: { type: \"string\", title: \"ZIP\" },\n country: { type: \"string\", title: \"Country\" },\n },\n required: [\"street\", \"city\"],\n },\n },\n },\n required: [\"first_name\", \"last_name\"],\n};\n\n// An audit-event-like schema: a fixed envelope (actor, targets) with three\n// extensible metadata containers. Used to demo scoped editing.\nconst AUDIT_SCHEMA: JsonSchema = {\n title: \"AuditEvent\",\n type: \"object\",\n properties: {\n actor: {\n type: \"object\",\n title: \"Actor\",\n properties: {\n type: { type: \"string\", title: \"Type\" },\n id: { type: \"string\", title: \"ID\" },\n metadata: {\n type: \"object\",\n title: \"Actor metadata\",\n properties: { role: { type: \"string\", title: \"Role\" } },\n },\n },\n },\n targets: {\n type: \"array\",\n title: \"Targets\",\n items: {\n type: \"object\",\n properties: {\n type: { type: \"string\", title: \"Type\" },\n id: { type: \"string\", title: \"ID\" },\n metadata: {\n type: \"object\",\n title: \"Target metadata\",\n properties: { ward: { type: \"string\", title: \"Ward\" } },\n },\n },\n },\n },\n metadata: {\n type: \"object\",\n title: \"Metadata\",\n properties: { reason: { type: \"string\", title: \"Reason\" } },\n },\n },\n};\n\n// A schema exercising every logic construct the designer can author: a oneOf\n// discriminated variant (payment method), if/then/else conditionals (authored\n// as allOf members), a const-tagged field, and a nullable anyOf optional field.\n// x-ui-order places each conditional field right after the property it depends\n// on (see docs/design/schema-designer-logic-authoring.md, ordering note).\nconst LOGIC_SCHEMA: JsonSchema = {\n title: \"Checkout\",\n type: \"object\",\n // A reusable definition referenced by $ref (shows read-only expansion).\n $defs: {\n Address: {\n type: \"object\",\n properties: {\n street: { type: \"string\", title: \"Street\" },\n city: { type: \"string\", title: \"City\" },\n zip: { type: \"string\", title: \"ZIP\" },\n },\n },\n },\n \"x-ui-order\": [\n \"schema_version\",\n \"amount\",\n \"requires_approval\",\n \"currency\",\n \"expedited\",\n \"delivery_window\",\n \"gift_wrap\",\n \"gift_message\",\n \"shipping_address\",\n \"note\",\n \"payment\",\n ],\n properties: {\n // A $ref to the shared Address definition (read-only in the tree).\n shipping_address: { $ref: \"#/$defs/Address\", title: \"Shipping address\" },\n // A fixed value carried by every document (const authoring).\n schema_version: {\n type: \"string\",\n title: \"Schema version\",\n const: \"checkout/v1\",\n },\n amount: { type: \"number\", title: \"Amount\", minimum: 0 },\n currency: {\n type: \"string\",\n title: \"Currency\",\n enum: [\"EUR\", \"USD\", \"GBP\"],\n },\n expedited: { type: \"boolean\", title: \"Expedited\" },\n gift_wrap: { type: \"boolean\", title: \"Gift wrap\" },\n // Declarative visibility rule (x-ui-rule): declared at its own position,\n // shown only when gift_wrap is checked. Contrast with the if/then/else\n // fields above, which are structurally added by their conditionals.\n gift_message: {\n type: \"string\",\n title: \"Gift message\",\n \"x-ui-rule\": {\n effect: \"show\",\n condition: { scope: \"/gift_wrap\", schema: { const: true } },\n },\n },\n // Nullable optional (anyOf [T, null]) -- the renderer unwraps to T.\n note: {\n title: \"Note (optional)\",\n anyOf: [{ type: \"string\" }, { type: \"null\" }],\n },\n // A discriminated union (oneOf): the payment method.\n payment: {\n type: \"object\",\n title: \"Payment method\",\n discriminator: { propertyName: \"kind\" },\n oneOf: [\n {\n title: \"Card\",\n properties: {\n kind: { const: \"card\" },\n card_number: { type: \"string\", title: \"Card number\" },\n cvc: { type: \"string\", title: \"CVC\" },\n },\n },\n {\n title: \"Bank transfer\",\n properties: {\n kind: { const: \"bank\" },\n iban: { type: \"string\", title: \"IBAN\" },\n },\n },\n {\n title: \"Cash\",\n properties: { kind: { const: \"cash\" } },\n },\n ],\n },\n },\n required: [\"amount\", \"currency\"],\n // Conditionals (if/then/else) authored as allOf members.\n allOf: [\n {\n // Large amounts require an approval reference.\n if: {\n properties: { amount: { exclusiveMinimum: 1000 } },\n required: [\"amount\"],\n },\n then: {\n properties: {\n requires_approval: {\n type: \"string\",\n title: \"Approval reference\",\n },\n },\n required: [\"requires_approval\"],\n },\n },\n {\n // Expedited orders ask for a delivery window; otherwise none.\n if: {\n properties: { expedited: { const: true } },\n required: [\"expedited\"],\n },\n then: {\n properties: {\n delivery_window: {\n type: \"string\",\n title: \"Delivery window\",\n enum: [\"morning\", \"afternoon\", \"evening\"],\n },\n },\n },\n },\n ],\n};\n\nconst AUDIT_EDITABLE_PATHS = [\n \"/properties/metadata/properties\",\n \"/properties/actor/properties/metadata/properties\",\n \"/properties/targets/items/properties/metadata/properties\",\n];\n\ntype ProfileKey = \"full\" | \"data\" | \"scoped\" | \"structure\" | \"logic\";\n\ninterface Profile {\n label: string;\n description: string;\n schema: JsonSchema;\n capabilities?: SchemaDesignerCapabilities;\n readOnly?: boolean;\n}\n\nconst PROFILES: Record<ProfileKey, Profile> = {\n full: {\n label: \"Full (schema + uiSchema)\",\n description: \"Default: author the schema and its form presentation hints.\",\n schema: SAMPLE_SCHEMA,\n capabilities: { previews: [\"form\", \"table\", \"json\", \"capabilities\"] },\n },\n data: {\n label: \"Data schema only\",\n description:\n \"Pure JSON Schema (audit, terminology): no UI/Combined tabs, JSON preview only.\",\n schema: SAMPLE_SCHEMA,\n capabilities: { mode: \"data\", previews: [\"json\", \"capabilities\"] },\n },\n scoped: {\n label: \"Scoped (audit event)\",\n description:\n \"Fixed envelope; only the three metadata containers are editable.\",\n schema: AUDIT_SCHEMA,\n capabilities: {\n mode: \"data\",\n editablePaths: AUDIT_EDITABLE_PATHS,\n previews: [\"json\", \"capabilities\"],\n },\n },\n structure: {\n label: \"Structure only (no preview)\",\n description: \"Tree + inspector only; the center preview pane is hidden.\",\n schema: SAMPLE_SCHEMA,\n capabilities: { mode: \"data\", previews: [] },\n },\n logic: {\n label: \"Logic (variants + conditionals)\",\n description:\n \"Shows every logic construct: a oneOf variant, if/then/else conditionals, a const field, and a nullable optional.\",\n schema: LOGIC_SCHEMA,\n capabilities: { previews: [\"form\", \"table\", \"json\", \"capabilities\"] },\n },\n};\n\n/**\n * PlaySchemaDesigner -- exercises SchemaDesigner: visually author a JsonSchema\n * (and its uiSchema presentation hints), with a live preview. The profile\n * switcher presets the capability profile (data/full triage, scoped editing,\n * read-only); the in-designer Capabilities tab tweaks it live.\n */\nexport default function PlaySchemaDesigner() {\n const [profileKey, setProfileKey] = useState<ProfileKey>(\"full\");\n const profile = PROFILES[profileKey];\n\n const [schema, setSchema] = useState<JsonSchema>(profile.schema);\n const [uiSchema, setUiSchema] = useState<Record<string, UISchema>>({});\n\n const selectProfile = (key: ProfileKey) => {\n setProfileKey(key);\n setSchema(PROFILES[key].schema);\n setUiSchema({});\n };\n\n return (\n <div className=\"w-full flex flex-col gap-3 h-[calc(100vh-8rem)]\">\n <div>\n <h1>Schema Designer</h1>\n <p className=\"text-sm text-muted-foreground mb-3\">\n Visually author a JSON Schema and its UI presentation hints. Edits\n flow through onChange as a valid schema + uiSchema.\n </p>\n </div>\n\n <div className=\"flex items-center gap-3\">\n <label\n htmlFor=\"capability-profile\"\n className=\"shrink-0 text-sm font-medium\"\n >\n Capability profile\n </label>\n <div className=\"w-72\">\n <FormSelect\n id=\"capability-profile\"\n name=\"profile\"\n value={profileKey}\n options={(Object.keys(PROFILES) as ProfileKey[]).map((k) => ({\n value: k,\n label: PROFILES[k].label,\n }))}\n onChange={(v) => selectProfile((v as ProfileKey) ?? \"full\")}\n clearable={false}\n />\n </div>\n <p className=\"text-sm text-muted-foreground\">{profile.description}</p>\n </div>\n\n <div style={{ flex: 1, minHeight: 0 }}>\n <SchemaDesigner\n key={profileKey}\n schema={schema}\n uiSchema={uiSchema}\n capabilities={profile.capabilities}\n readOnly={profile.readOnly}\n onChange={(nextSchema, nextUiSchema) => {\n setSchema(nextSchema);\n setUiSchema(nextUiSchema);\n }}\n />\n </div>\n </div>\n );\n}\n"],"mappings":";AAAA,SAAS,gBAAgB;AACzB;AAAA,EACE;AAAA,OAEK;AACP,SAAS,kBAAkB;AAwSrB,SACE,KADF;AArSN,IAAM,gBAA4B;AAAA,EAChC,OAAO;AAAA,EACP,MAAM;AAAA,EACN,YAAY;AAAA,IACV,YAAY,EAAE,MAAM,UAAU,OAAO,cAAc,WAAW,EAAE;AAAA,IAChE,WAAW,EAAE,MAAM,UAAU,OAAO,aAAa,WAAW,EAAE;AAAA,IAC9D,eAAe,EAAE,MAAM,UAAU,QAAQ,QAAQ,OAAO,gBAAgB;AAAA,IACxE,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM,CAAC,QAAQ,UAAU,SAAS,SAAS;AAAA,IAC7C;AAAA,IACA,QAAQ,EAAE,MAAM,WAAW,OAAO,SAAS;AAAA,IAC3C,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,YAAY;AAAA,QACV,OAAO,EAAE,MAAM,UAAU,QAAQ,SAAS,OAAO,QAAQ;AAAA,QACzD,OAAO,EAAE,MAAM,UAAU,OAAO,QAAQ;AAAA,MAC1C;AAAA,MACA,UAAU,CAAC,OAAO;AAAA,IACpB;AAAA,IACA,WAAW;AAAA,MACT,MAAM;AAAA,MACN,OAAO;AAAA,MACP,UAAU;AAAA,MACV,UAAU;AAAA,MACV,OAAO;AAAA,QACL,MAAM;AAAA,QACN,YAAY;AAAA,UACV,QAAQ,EAAE,MAAM,UAAU,OAAO,SAAS;AAAA,UAC1C,MAAM,EAAE,MAAM,UAAU,OAAO,OAAO;AAAA,UACtC,KAAK,EAAE,MAAM,UAAU,OAAO,MAAM;AAAA,UACpC,SAAS,EAAE,MAAM,UAAU,OAAO,UAAU;AAAA,QAC9C;AAAA,QACA,UAAU,CAAC,UAAU,MAAM;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAAA,EACA,UAAU,CAAC,cAAc,WAAW;AACtC;AAIA,IAAM,eAA2B;AAAA,EAC/B,OAAO;AAAA,EACP,MAAM;AAAA,EACN,YAAY;AAAA,IACV,OAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,YAAY;AAAA,QACV,MAAM,EAAE,MAAM,UAAU,OAAO,OAAO;AAAA,QACtC,IAAI,EAAE,MAAM,UAAU,OAAO,KAAK;AAAA,QAClC,UAAU;AAAA,UACR,MAAM;AAAA,UACN,OAAO;AAAA,UACP,YAAY,EAAE,MAAM,EAAE,MAAM,UAAU,OAAO,OAAO,EAAE;AAAA,QACxD;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO;AAAA,QACL,MAAM;AAAA,QACN,YAAY;AAAA,UACV,MAAM,EAAE,MAAM,UAAU,OAAO,OAAO;AAAA,UACtC,IAAI,EAAE,MAAM,UAAU,OAAO,KAAK;AAAA,UAClC,UAAU;AAAA,YACR,MAAM;AAAA,YACN,OAAO;AAAA,YACP,YAAY,EAAE,MAAM,EAAE,MAAM,UAAU,OAAO,OAAO,EAAE;AAAA,UACxD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,UAAU;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,MACP,YAAY,EAAE,QAAQ,EAAE,MAAM,UAAU,OAAO,SAAS,EAAE;AAAA,IAC5D;AAAA,EACF;AACF;AAOA,IAAM,eAA2B;AAAA,EAC/B,OAAO;AAAA,EACP,MAAM;AAAA;AAAA,EAEN,OAAO;AAAA,IACL,SAAS;AAAA,MACP,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ,EAAE,MAAM,UAAU,OAAO,SAAS;AAAA,QAC1C,MAAM,EAAE,MAAM,UAAU,OAAO,OAAO;AAAA,QACtC,KAAK,EAAE,MAAM,UAAU,OAAO,MAAM;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAAA,EACA,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,YAAY;AAAA;AAAA,IAEV,kBAAkB,EAAE,MAAM,mBAAmB,OAAO,mBAAmB;AAAA;AAAA,IAEvE,gBAAgB;AAAA,MACd,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,IACA,QAAQ,EAAE,MAAM,UAAU,OAAO,UAAU,SAAS,EAAE;AAAA,IACtD,UAAU;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM,CAAC,OAAO,OAAO,KAAK;AAAA,IAC5B;AAAA,IACA,WAAW,EAAE,MAAM,WAAW,OAAO,YAAY;AAAA,IACjD,WAAW,EAAE,MAAM,WAAW,OAAO,YAAY;AAAA;AAAA;AAAA;AAAA,IAIjD,cAAc;AAAA,MACZ,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,QACX,QAAQ;AAAA,QACR,WAAW,EAAE,OAAO,cAAc,QAAQ,EAAE,OAAO,KAAK,EAAE;AAAA,MAC5D;AAAA,IACF;AAAA;AAAA,IAEA,MAAM;AAAA,MACJ,OAAO;AAAA,MACP,OAAO,CAAC,EAAE,MAAM,SAAS,GAAG,EAAE,MAAM,OAAO,CAAC;AAAA,IAC9C;AAAA;AAAA,IAEA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,eAAe,EAAE,cAAc,OAAO;AAAA,MACtC,OAAO;AAAA,QACL;AAAA,UACE,OAAO;AAAA,UACP,YAAY;AAAA,YACV,MAAM,EAAE,OAAO,OAAO;AAAA,YACtB,aAAa,EAAE,MAAM,UAAU,OAAO,cAAc;AAAA,YACpD,KAAK,EAAE,MAAM,UAAU,OAAO,MAAM;AAAA,UACtC;AAAA,QACF;AAAA,QACA;AAAA,UACE,OAAO;AAAA,UACP,YAAY;AAAA,YACV,MAAM,EAAE,OAAO,OAAO;AAAA,YACtB,MAAM,EAAE,MAAM,UAAU,OAAO,OAAO;AAAA,UACxC;AAAA,QACF;AAAA,QACA;AAAA,UACE,OAAO;AAAA,UACP,YAAY,EAAE,MAAM,EAAE,OAAO,OAAO,EAAE;AAAA,QACxC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,UAAU,CAAC,UAAU,UAAU;AAAA;AAAA,EAE/B,OAAO;AAAA,IACL;AAAA;AAAA,MAEE,IAAI;AAAA,QACF,YAAY,EAAE,QAAQ,EAAE,kBAAkB,IAAK,EAAE;AAAA,QACjD,UAAU,CAAC,QAAQ;AAAA,MACrB;AAAA,MACA,MAAM;AAAA,QACJ,YAAY;AAAA,UACV,mBAAmB;AAAA,YACjB,MAAM;AAAA,YACN,OAAO;AAAA,UACT;AAAA,QACF;AAAA,QACA,UAAU,CAAC,mBAAmB;AAAA,MAChC;AAAA,IACF;AAAA,IACA;AAAA;AAAA,MAEE,IAAI;AAAA,QACF,YAAY,EAAE,WAAW,EAAE,OAAO,KAAK,EAAE;AAAA,QACzC,UAAU,CAAC,WAAW;AAAA,MACxB;AAAA,MACA,MAAM;AAAA,QACJ,YAAY;AAAA,UACV,iBAAiB;AAAA,YACf,MAAM;AAAA,YACN,OAAO;AAAA,YACP,MAAM,CAAC,WAAW,aAAa,SAAS;AAAA,UAC1C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAM,uBAAuB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF;AAYA,IAAM,WAAwC;AAAA,EAC5C,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,cAAc,EAAE,UAAU,CAAC,QAAQ,SAAS,QAAQ,cAAc,EAAE;AAAA,EACtE;AAAA,EACA,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,aACE;AAAA,IACF,QAAQ;AAAA,IACR,cAAc,EAAE,MAAM,QAAQ,UAAU,CAAC,QAAQ,cAAc,EAAE;AAAA,EACnE;AAAA,EACA,QAAQ;AAAA,IACN,OAAO;AAAA,IACP,aACE;AAAA,IACF,QAAQ;AAAA,IACR,cAAc;AAAA,MACZ,MAAM;AAAA,MACN,eAAe;AAAA,MACf,UAAU,CAAC,QAAQ,cAAc;AAAA,IACnC;AAAA,EACF;AAAA,EACA,WAAW;AAAA,IACT,OAAO;AAAA,IACP,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,cAAc,EAAE,MAAM,QAAQ,UAAU,CAAC,EAAE;AAAA,EAC7C;AAAA,EACA,OAAO;AAAA,IACL,OAAO;AAAA,IACP,aACE;AAAA,IACF,QAAQ;AAAA,IACR,cAAc,EAAE,UAAU,CAAC,QAAQ,SAAS,QAAQ,cAAc,EAAE;AAAA,EACtE;AACF;AAQe,SAAR,qBAAsC;AAC3C,QAAM,CAAC,YAAY,aAAa,IAAI,SAAqB,MAAM;AAC/D,QAAM,UAAU,SAAS,UAAU;AAEnC,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAqB,QAAQ,MAAM;AAC/D,QAAM,CAAC,UAAU,WAAW,IAAI,SAAmC,CAAC,CAAC;AAErE,QAAM,gBAAgB,CAAC,QAAoB;AACzC,kBAAc,GAAG;AACjB,cAAU,SAAS,GAAG,EAAE,MAAM;AAC9B,gBAAY,CAAC,CAAC;AAAA,EAChB;AAEA,SACE,qBAAC,SAAI,WAAU,mDACb;AAAA,yBAAC,SACC;AAAA,0BAAC,QAAG,6BAAe;AAAA,MACnB,oBAAC,OAAE,WAAU,sCAAqC,oIAGlD;AAAA,OACF;AAAA,IAEA,qBAAC,SAAI,WAAU,2BACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,WAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,MACA,oBAAC,SAAI,WAAU,QACb;AAAA,QAAC;AAAA;AAAA,UACC,IAAG;AAAA,UACH,MAAK;AAAA,UACL,OAAO;AAAA,UACP,SAAU,OAAO,KAAK,QAAQ,EAAmB,IAAI,CAAC,OAAO;AAAA,YAC3D,OAAO;AAAA,YACP,OAAO,SAAS,CAAC,EAAE;AAAA,UACrB,EAAE;AAAA,UACF,UAAU,CAAC,MAAM,cAAe,KAAoB,MAAM;AAAA,UAC1D,WAAW;AAAA;AAAA,MACb,GACF;AAAA,MACA,oBAAC,OAAE,WAAU,iCAAiC,kBAAQ,aAAY;AAAA,OACpE;AAAA,IAEA,oBAAC,SAAI,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,GAClC;AAAA,MAAC;AAAA;AAAA,QAEC;AAAA,QACA;AAAA,QACA,cAAc,QAAQ;AAAA,QACtB,UAAU,QAAQ;AAAA,QAClB,UAAU,CAAC,YAAY,iBAAiB;AACtC,oBAAU,UAAU;AACpB,sBAAY,YAAY;AAAA,QAC1B;AAAA;AAAA,MARK;AAAA,IASP,GACF;AAAA,KACF;AAEJ;","names":[]}
@@ -19,6 +19,17 @@ import {
19
19
  Textarea,
20
20
  Checkbox,
21
21
  Label,
22
+ DateInput,
23
+ TimeInput,
24
+ DateTimeInput,
25
+ Select,
26
+ SelectTrigger,
27
+ SelectValue,
28
+ SelectContent,
29
+ SelectItem,
30
+ SelectGroup,
31
+ SelectLabel,
32
+ SelectSeparator,
22
33
  Avatar,
23
34
  AvatarImage,
24
35
  AvatarFallback,
@@ -51,6 +62,299 @@ import {
51
62
  Copy
52
63
  } from "lucide-react";
53
64
  import { jsx, jsxs } from "react/jsx-runtime";
65
+ function SelectSection() {
66
+ const [fruit, setFruit] = useState("");
67
+ const [tz, setTz] = useState("cet");
68
+ return /* @__PURE__ */ jsx(
69
+ PlaygroundSection,
70
+ {
71
+ title: "Select",
72
+ description: "Single-value dropdown built on Radix Select. Styled trigger, keyboard navigable, with optional groups and labels. For searchable or entity-backed selection use FormSelect / EntitySelect instead.",
73
+ variant: "card",
74
+ children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-3", children: [
75
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
76
+ /* @__PURE__ */ jsx(Label, { htmlFor: "select-fruit", children: "Basic (with placeholder)" }),
77
+ /* @__PURE__ */ jsxs(Select, { value: fruit, onValueChange: setFruit, children: [
78
+ /* @__PURE__ */ jsx(SelectTrigger, { id: "select-fruit", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select a fruit" }) }),
79
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
80
+ /* @__PURE__ */ jsx(SelectItem, { value: "apple", children: "Apple" }),
81
+ /* @__PURE__ */ jsx(SelectItem, { value: "banana", children: "Banana" }),
82
+ /* @__PURE__ */ jsx(SelectItem, { value: "cherry", children: "Cherry" }),
83
+ /* @__PURE__ */ jsx(SelectItem, { value: "durian", disabled: true, children: "Durian (out of stock)" })
84
+ ] })
85
+ ] }),
86
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-tertiary-foreground", children: [
87
+ "Value: ",
88
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: fruit || "(none)" })
89
+ ] })
90
+ ] }),
91
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
92
+ /* @__PURE__ */ jsx(Label, { htmlFor: "select-tz", children: "Grouped options" }),
93
+ /* @__PURE__ */ jsxs(Select, { value: tz, onValueChange: setTz, children: [
94
+ /* @__PURE__ */ jsx(SelectTrigger, { id: "select-tz", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
95
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
96
+ /* @__PURE__ */ jsxs(SelectGroup, { children: [
97
+ /* @__PURE__ */ jsx(SelectLabel, { children: "Europe" }),
98
+ /* @__PURE__ */ jsx(SelectItem, { value: "cet", children: "Central European" }),
99
+ /* @__PURE__ */ jsx(SelectItem, { value: "gmt", children: "Greenwich Mean" })
100
+ ] }),
101
+ /* @__PURE__ */ jsx(SelectSeparator, {}),
102
+ /* @__PURE__ */ jsxs(SelectGroup, { children: [
103
+ /* @__PURE__ */ jsx(SelectLabel, { children: "Americas" }),
104
+ /* @__PURE__ */ jsx(SelectItem, { value: "est", children: "Eastern" }),
105
+ /* @__PURE__ */ jsx(SelectItem, { value: "pst", children: "Pacific" })
106
+ ] })
107
+ ] })
108
+ ] }),
109
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-tertiary-foreground", children: [
110
+ "Value: ",
111
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: tz })
112
+ ] })
113
+ ] }),
114
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
115
+ /* @__PURE__ */ jsx(Label, { htmlFor: "select-disabled", children: "Disabled" }),
116
+ /* @__PURE__ */ jsxs(Select, { disabled: true, value: "apple", children: [
117
+ /* @__PURE__ */ jsx(SelectTrigger, { id: "select-disabled", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
118
+ /* @__PURE__ */ jsx(SelectContent, { children: /* @__PURE__ */ jsx(SelectItem, { value: "apple", children: "Apple" }) })
119
+ ] })
120
+ ] })
121
+ ] })
122
+ }
123
+ );
124
+ }
125
+ function DateInputSection() {
126
+ const [dateDay, setDateDay] = useState("2026-06-15");
127
+ const [dateMonth, setDateMonth] = useState("1980-06");
128
+ const [dateYear, setDateYear] = useState("1980");
129
+ const [dateEmpty, setDateEmpty] = useState("");
130
+ return /* @__PURE__ */ jsx(
131
+ PlaygroundSection,
132
+ {
133
+ title: "Date Input",
134
+ description: "Text input with a calendar popover. Value is a partial ISO 8601 date string (YYYY, YYYY-MM, or YYYY-MM-DD depending on precision). Display and parsing follow the playground locale (gear icon, top-right of the Overview page); values stay ISO. Supports typed entry, calendar drill-down, and quick entry ('t', 'today', '.').",
135
+ variant: "card",
136
+ children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2", children: [
137
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
138
+ /* @__PURE__ */ jsx(Label, { htmlFor: "date-day", children: "Day precision (YYYY-MM-DD)" }),
139
+ /* @__PURE__ */ jsx(DateInput, { id: "date-day", value: dateDay, onChange: setDateDay }),
140
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-tertiary-foreground", children: [
141
+ "Value: ",
142
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: dateDay || "(empty)" })
143
+ ] })
144
+ ] }),
145
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
146
+ /* @__PURE__ */ jsx(Label, { htmlFor: "date-month", children: "Month precision (YYYY-MM)" }),
147
+ /* @__PURE__ */ jsx(
148
+ DateInput,
149
+ {
150
+ id: "date-month",
151
+ precision: "month",
152
+ value: dateMonth,
153
+ onChange: setDateMonth
154
+ }
155
+ ),
156
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-tertiary-foreground", children: [
157
+ "Value: ",
158
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: dateMonth || "(empty)" })
159
+ ] })
160
+ ] }),
161
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
162
+ /* @__PURE__ */ jsx(Label, { htmlFor: "date-year", children: "Year precision (YYYY)" }),
163
+ /* @__PURE__ */ jsx(
164
+ DateInput,
165
+ {
166
+ id: "date-year",
167
+ precision: "year",
168
+ value: dateYear,
169
+ onChange: setDateYear
170
+ }
171
+ ),
172
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-tertiary-foreground", children: [
173
+ "Value: ",
174
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: dateYear || "(empty)" })
175
+ ] })
176
+ ] }),
177
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
178
+ /* @__PURE__ */ jsx(Label, { htmlFor: "date-empty", children: "Empty + clearable" }),
179
+ /* @__PURE__ */ jsx(
180
+ DateInput,
181
+ {
182
+ id: "date-empty",
183
+ value: dateEmpty,
184
+ onChange: setDateEmpty,
185
+ placeholder: "Pick or type a date"
186
+ }
187
+ ),
188
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-tertiary-foreground", children: [
189
+ "Value: ",
190
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: dateEmpty || "(empty)" })
191
+ ] })
192
+ ] }),
193
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
194
+ /* @__PURE__ */ jsx(Label, { htmlFor: "date-disabled", children: "Disabled" }),
195
+ /* @__PURE__ */ jsx(
196
+ DateInput,
197
+ {
198
+ id: "date-disabled",
199
+ value: "2026-01-01",
200
+ onChange: () => {
201
+ },
202
+ disabled: true
203
+ }
204
+ )
205
+ ] }),
206
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
207
+ /* @__PURE__ */ jsx(Label, { htmlFor: "date-error", children: "With error" }),
208
+ /* @__PURE__ */ jsx(
209
+ DateInput,
210
+ {
211
+ id: "date-error",
212
+ value: "",
213
+ onChange: () => {
214
+ },
215
+ error: "This date is required"
216
+ }
217
+ )
218
+ ] })
219
+ ] })
220
+ }
221
+ );
222
+ }
223
+ function TimeInputSection() {
224
+ const [timeMin, setTimeMin] = useState("09:30");
225
+ const [timeSec, setTimeSec] = useState("21:05:07");
226
+ const [timeEmpty, setTimeEmpty] = useState("");
227
+ return /* @__PURE__ */ jsx(
228
+ PlaygroundSection,
229
+ {
230
+ title: "Time Input",
231
+ description: "Zone-free time of day. Value is a normalized ISO time string (HH:mm or HH:mm:ss). No timezone. Supports lenient typed entry ('9', '930', '9:30') and quick entry (type 'n', 'now', or '.' for the current time).",
232
+ variant: "card",
233
+ children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2", children: [
234
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
235
+ /* @__PURE__ */ jsx(Label, { htmlFor: "time-min", children: "Minute granularity (HH:mm)" }),
236
+ /* @__PURE__ */ jsx(TimeInput, { id: "time-min", value: timeMin, onChange: setTimeMin }),
237
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-tertiary-foreground", children: [
238
+ "Value: ",
239
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: timeMin || "(empty)" })
240
+ ] })
241
+ ] }),
242
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
243
+ /* @__PURE__ */ jsx(Label, { htmlFor: "time-sec", children: "Second granularity (HH:mm:ss)" }),
244
+ /* @__PURE__ */ jsx(
245
+ TimeInput,
246
+ {
247
+ id: "time-sec",
248
+ granularity: "second",
249
+ value: timeSec,
250
+ onChange: setTimeSec
251
+ }
252
+ ),
253
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-tertiary-foreground", children: [
254
+ "Value: ",
255
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: timeSec || "(empty)" })
256
+ ] })
257
+ ] }),
258
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
259
+ /* @__PURE__ */ jsx(Label, { htmlFor: "time-empty", children: "Empty + clearable" }),
260
+ /* @__PURE__ */ jsx(
261
+ TimeInput,
262
+ {
263
+ id: "time-empty",
264
+ value: timeEmpty,
265
+ onChange: setTimeEmpty
266
+ }
267
+ ),
268
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-tertiary-foreground", children: [
269
+ "Value: ",
270
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: timeEmpty || "(empty)" })
271
+ ] })
272
+ ] }),
273
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
274
+ /* @__PURE__ */ jsx(Label, { htmlFor: "time-error", children: "With error" }),
275
+ /* @__PURE__ */ jsx(
276
+ TimeInput,
277
+ {
278
+ id: "time-error",
279
+ value: "",
280
+ onChange: () => {
281
+ },
282
+ error: "This time is required"
283
+ }
284
+ )
285
+ ] })
286
+ ] })
287
+ }
288
+ );
289
+ }
290
+ function DateTimeInputSection() {
291
+ const [dt, setDt] = useState("2026-06-15T09:30");
292
+ const [dtZoned, setDtZoned] = useState("2026-11-02T10:00");
293
+ const [dtEmpty, setDtEmpty] = useState("");
294
+ return /* @__PURE__ */ jsx(
295
+ PlaygroundSection,
296
+ {
297
+ title: "Date-Time Input",
298
+ description: "Combined date + time for a plain wall-clock datetime (YYYY-MM-DDTHH:mm[:ss]), no timezone. Resolving to an absolute instant is the consumer's job. The optional timeZone prop is a display-only hint, never applied or user-entered.",
299
+ variant: "card",
300
+ children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2", children: [
301
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
302
+ /* @__PURE__ */ jsx(Label, { children: "Plain wall-clock" }),
303
+ /* @__PURE__ */ jsx(DateTimeInput, { idPrefix: "dt", value: dt, onChange: setDt }),
304
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-tertiary-foreground", children: [
305
+ "Value: ",
306
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: dt || "(empty)" })
307
+ ] })
308
+ ] }),
309
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
310
+ /* @__PURE__ */ jsx(Label, { children: "With timezone hint" }),
311
+ /* @__PURE__ */ jsx(
312
+ DateTimeInput,
313
+ {
314
+ idPrefix: "dt-zoned",
315
+ value: dtZoned,
316
+ onChange: setDtZoned,
317
+ timeZone: "Europe/Berlin"
318
+ }
319
+ ),
320
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-tertiary-foreground", children: [
321
+ "Value: ",
322
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: dtZoned || "(empty)" })
323
+ ] })
324
+ ] }),
325
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
326
+ /* @__PURE__ */ jsx(Label, { children: "Second granularity + empty" }),
327
+ /* @__PURE__ */ jsx(
328
+ DateTimeInput,
329
+ {
330
+ idPrefix: "dt-empty",
331
+ granularity: "second",
332
+ value: dtEmpty,
333
+ onChange: setDtEmpty
334
+ }
335
+ ),
336
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-tertiary-foreground", children: [
337
+ "Value: ",
338
+ /* @__PURE__ */ jsx("span", { className: "font-mono", children: dtEmpty || "(empty)" })
339
+ ] })
340
+ ] }),
341
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
342
+ /* @__PURE__ */ jsx(Label, { children: "Disabled" }),
343
+ /* @__PURE__ */ jsx(
344
+ DateTimeInput,
345
+ {
346
+ idPrefix: "dt-disabled",
347
+ value: "2026-01-01T08:00",
348
+ onChange: () => {
349
+ },
350
+ disabled: true
351
+ }
352
+ )
353
+ ] })
354
+ ] })
355
+ }
356
+ );
357
+ }
54
358
  function PlayCoreComponents() {
55
359
  const [spinnerSize, setSpinnerSize] = useState("md");
56
360
  const clipboard = useClipboard({ timeout: 2e3 });
@@ -598,6 +902,10 @@ function PlayCoreComponents() {
598
902
  ] })
599
903
  }
600
904
  ),
905
+ /* @__PURE__ */ jsx(SelectSection, {}),
906
+ /* @__PURE__ */ jsx(DateInputSection, {}),
907
+ /* @__PURE__ */ jsx(TimeInputSection, {}),
908
+ /* @__PURE__ */ jsx(DateTimeInputSection, {}),
601
909
  /* @__PURE__ */ jsx(
602
910
  PlaygroundSection,
603
911
  {
@@ -982,4 +1290,4 @@ function PlayCoreComponents() {
982
1290
  export {
983
1291
  PlayCoreComponents
984
1292
  };
985
- //# sourceMappingURL=chunk-Q6NLY2BZ.js.map
1293
+ //# sourceMappingURL=chunk-6WI3N7JI.js.map