clom-renderer 1.0.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.
@@ -0,0 +1,9 @@
1
+ import { ClomOutput } from './types';
2
+ interface Props {
3
+ /** Raw CLOM JSON output. Discriminated by the `interaction` field. */
4
+ data: ClomOutput;
5
+ onSubmit: (text: string) => void;
6
+ locked: boolean;
7
+ }
8
+ export declare function ClomRenderer({ data, onSubmit, locked }: Props): import("react/jsx-runtime").JSX.Element | null;
9
+ export {};
package/dist/index.cjs ADDED
@@ -0,0 +1,3 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`react`),t=require(`react/jsx-runtime`);var n={card:`_card_148uw_16`,field:`_field_148uw_30`,fieldLabel:`_fieldLabel_148uw_36`,required:`_required_148uw_42`,fieldInput:`_fieldInput_148uw_46`,fieldTextarea:`_fieldTextarea_148uw_47`,optionsRow:`_optionsRow_148uw_65`,optionBtn:`_optionBtn_148uw_71`,checkList:`_checkList_148uw_89`,checkItem:`_checkItem_148uw_95`,checkbox:`_checkbox_148uw_104`,submitBtn:`_submitBtn_148uw_112`,interactionTitle:`_interactionTitle_148uw_133`,hint:`_hint_148uw_140`,errorText:`_errorText_148uw_146`,addressGrid:`_addressGrid_148uw_154`,otpGrid:`_otpGrid_148uw_162`,otpBox:`_otpBox_148uw_167`,starRow:`_starRow_148uw_188`,star:`_star_148uw_188`,starActive:`_starActive_148uw_205`,fileZone:`_fileZone_148uw_212`,fileHint:`_fileHint_148uw_226`,fileName:`_fileName_148uw_231`,cardGrid:`_cardGrid_148uw_239`,cardItem:`_cardItem_148uw_245`,cardImage:`_cardImage_148uw_265`,cardBody:`_cardBody_148uw_271`,cardTitle:`_cardTitle_148uw_278`,cardSubtitle:`_cardSubtitle_148uw_284`,cardMeta:`_cardMeta_148uw_289`,cardPrice:`_cardPrice_148uw_296`,cardBadge:`_cardBadge_148uw_302`,confirmSummary:`_confirmSummary_148uw_313`,confirmKey:`_confirmKey_148uw_319`,confirmVal:`_confirmVal_148uw_327`,confirmActions:`_confirmActions_148uw_332`,cancelBtn:`_cancelBtn_148uw_339`,timeline:`_timeline_148uw_359`,timelineStep:`_timelineStep_148uw_365`,tl_completed:`_tl_completed_148uw_383`,timelineDot:`_timelineDot_148uw_387`,tl_active:`_tl_active_148uw_404`,timelineContent:`_timelineContent_148uw_409`,timelineLabel:`_timelineLabel_148uw_415`,tl_pending:`_tl_pending_148uw_421`,timelineTs:`_timelineTs_148uw_425`,slotGrid:`_slotGrid_148uw_432`,slot:`_slot_148uw_432`,slotActive:`_slotActive_148uw_456`,tableWrap:`_tableWrap_148uw_464`,dataTable:`_dataTable_148uw_470`,stepperProgress:`_stepperProgress_148uw_498`,stepperDot:`_stepperDot_148uw_505`,stepperDone:`_stepperDone_148uw_513`,stepperCurrent:`_stepperCurrent_148uw_517`,stepperLabel:`_stepperLabel_148uw_523`,stepperNav:`_stepperNav_148uw_530`};function r({data:e,onSubmit:n,locked:r}){if(r)return null;let _=e;switch(_.interaction){case`form`:return(0,t.jsx)(i,{title:_.title,fields:_.fields,onSubmit:n});case`address`:return(0,t.jsx)(i,{title:_.title??`Delivery Address`,fields:_.fields,onSubmit:n});case`select`:return(0,t.jsx)(a,{options:_.options,onSubmit:n});case`multiselect`:return(0,t.jsx)(o,{options:_.options,onSubmit:n});case`date_picker`:return(0,t.jsx)(s,{label:_.label,minDate:_.min_date,maxDate:_.max_date,onSubmit:n});case`otp`:return(0,t.jsx)(c,{label:_.label,length:_.length??6,hint:_.hint,onSubmit:n});case`rating`:return(0,t.jsx)(l,{label:_.label,max:_.max??5,labels:_.labels,onSubmit:n});case`file_upload`:return(0,t.jsx)(u,{label:_.label,accept:_.accept,maxMb:_.max_mb??10,onSubmit:n});case`card_grid`:return(0,t.jsx)(d,{title:_.title,cards:_.cards,onSubmit:n});case`confirmation_card`:return(0,t.jsx)(f,{title:_.title,summary:_.summary,actions:_.actions,onSubmit:n});case`timeline`:return(0,t.jsx)(p,{title:_.title,steps:_.steps});case`slot_picker`:return(0,t.jsx)(m,{title:_.title,slots:_.slots,onSubmit:n});case`data_table`:return(0,t.jsx)(h,{title:_.title,columns:_.columns,rows:_.rows});case`stepper`:return(0,t.jsx)(g,{title:_.title,steps:_.steps,currentStep:_.current_step,onSubmit:n});default:return null}}function i({title:r,fields:i,onSubmit:a}){let[o,s]=(0,e.useState)(()=>Object.fromEntries(i.map(e=>[e.key,e.prefilled_value??``])));function c(){let e=i.map(e=>`${e.label}: ${o[e.key]??``}`).filter((e,t)=>o[i[t].key]?.trim());e.length!==0&&a(e.join(`
2
+ `))}let l=i.filter(e=>e.required).every(e=>o[e.key]?.trim());return(0,t.jsxs)(`div`,{className:n.card,children:[r&&(0,t.jsx)(`p`,{className:n.interactionTitle,children:r}),(0,t.jsx)(`div`,{className:n.addressGrid,children:i.map(e=>(0,t.jsxs)(`div`,{className:n.field,children:[(0,t.jsxs)(`label`,{className:n.fieldLabel,children:[e.label,e.required&&(0,t.jsx)(`span`,{className:n.required,children:` *`})]}),e.type===`textarea`?(0,t.jsx)(`textarea`,{className:n.fieldTextarea,rows:3,value:o[e.key]??``,onChange:t=>s(n=>({...n,[e.key]:t.target.value}))}):(0,t.jsx)(`input`,{className:n.fieldInput,type:e.type===`date_picker`?`date`:e.type===`file_upload`?`file`:e.type,value:o[e.key]??``,onChange:t=>s(n=>({...n,[e.key]:t.target.value}))})]},e.key))}),(0,t.jsx)(`button`,{className:n.submitBtn,onClick:c,disabled:!l,children:`Send`})]})}function a({options:e,onSubmit:r}){return(0,t.jsx)(`div`,{className:n.card,children:(0,t.jsx)(`div`,{className:n.optionsRow,children:e.map(e=>(0,t.jsx)(`button`,{className:n.optionBtn,onClick:()=>r(e),children:e},e))})})}function o({options:r,onSubmit:i}){let[a,o]=(0,e.useState)(new Set);function s(e){o(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})}return(0,t.jsxs)(`div`,{className:n.card,children:[(0,t.jsx)(`div`,{className:n.checkList,children:r.map(e=>(0,t.jsxs)(`label`,{className:n.checkItem,children:[(0,t.jsx)(`input`,{type:`checkbox`,checked:a.has(e),onChange:()=>s(e),className:n.checkbox}),e]},e))}),(0,t.jsx)(`button`,{className:n.submitBtn,onClick:()=>i([...a].join(`, `)),disabled:a.size===0,children:`Confirm`})]})}function s({label:r,minDate:i,maxDate:a,onSubmit:o}){let[s,c]=(0,e.useState)(``);return(0,t.jsxs)(`div`,{className:n.card,children:[(0,t.jsx)(`label`,{className:n.fieldLabel,children:r}),(0,t.jsx)(`input`,{type:`date`,className:n.fieldInput,value:s,min:i,max:a,onChange:e=>c(e.target.value)}),(0,t.jsx)(`button`,{className:n.submitBtn,onClick:()=>o(`${r}: ${s}`),disabled:!s,children:`Confirm`})]})}function c({label:r,length:i,hint:a,onSubmit:o}){let[s,c]=(0,e.useState)(Array(i).fill(``)),l=(0,e.useRef)([]);function u(e,t){let n=t.replace(/\D/g,``).slice(-1),r=[...s];r[e]=n,c(r),n&&e<i-1&&l.current[e+1]?.focus()}function d(e,t){t.key===`Backspace`&&!s[e]&&e>0&&l.current[e-1]?.focus()}function f(e){let t=e.clipboardData.getData(`text`).replace(/\D/g,``).slice(0,i);t.length>0&&(c([...t.split(``),...Array(i-t.length).fill(``)]),l.current[Math.min(t.length,i-1)]?.focus()),e.preventDefault()}let p=s.join(``);return(0,t.jsxs)(`div`,{className:n.card,children:[(0,t.jsx)(`p`,{className:n.fieldLabel,children:r}),a&&(0,t.jsx)(`p`,{className:n.hint,children:a}),(0,t.jsx)(`div`,{className:n.otpGrid,onPaste:f,children:s.map((e,r)=>(0,t.jsx)(`input`,{ref:e=>{l.current[r]=e},className:n.otpBox,type:`text`,inputMode:`numeric`,maxLength:1,value:e,onChange:e=>u(r,e.target.value),onKeyDown:e=>d(r,e)},r))}),(0,t.jsx)(`button`,{className:n.submitBtn,onClick:()=>o(`${r}: ${p}`),disabled:p.length<i,children:`Verify`})]})}function l({label:r,max:i,labels:a,onSubmit:o}){let[s,c]=(0,e.useState)(0),[l,u]=(0,e.useState)(0);function d(e){u(e),o(`${r}: ${e}/${i}${a?.[e-1]?` (${a[e-1]})`:``}`)}return(0,t.jsxs)(`div`,{className:n.card,children:[(0,t.jsx)(`p`,{className:n.fieldLabel,children:r}),(0,t.jsx)(`div`,{className:n.starRow,children:Array.from({length:i},(e,t)=>t+1).map(e=>(0,t.jsx)(`button`,{className:`${n.star} ${e<=(s||l)?n.starActive:``}`,onMouseEnter:()=>c(e),onMouseLeave:()=>c(0),onClick:()=>d(e),"aria-label":`${e} star${e===1?``:`s`}`,children:`★`},e))}),a&&s>0&&(0,t.jsx)(`p`,{className:n.hint,children:a[s-1]})]})}function u({label:r,accept:i,maxMb:a,onSubmit:o}){let[s,c]=(0,e.useState)(null),[l,u]=(0,e.useState)(null),d=(0,e.useRef)(null);function f(e){if(e.size>a*1024*1024){u(`File must be under ${a} MB`);return}u(null),c(e.name)}function p(e){let t=e.target.files?.[0];t&&f(t)}function m(e){e.preventDefault();let t=e.dataTransfer.files?.[0];t&&f(t)}return(0,t.jsxs)(`div`,{className:n.card,children:[(0,t.jsx)(`p`,{className:n.fieldLabel,children:r}),(0,t.jsxs)(`div`,{className:n.fileZone,onClick:()=>d.current?.click(),onDragOver:e=>e.preventDefault(),onDrop:m,children:[(0,t.jsx)(`input`,{ref:d,type:`file`,accept:i,style:{display:`none`},onChange:p}),s?(0,t.jsx)(`span`,{className:n.fileName,children:s}):(0,t.jsx)(`span`,{className:n.fileHint,children:`Tap to choose or drag a file here`})]}),l&&(0,t.jsx)(`p`,{className:n.errorText,children:l}),(0,t.jsx)(`button`,{className:n.submitBtn,onClick:()=>o(`${r}: ${s}`),disabled:!s,children:`Upload`})]})}function d({title:e,cards:r,onSubmit:i}){return(0,t.jsxs)(`div`,{className:n.card,children:[e&&(0,t.jsx)(`p`,{className:n.interactionTitle,children:e}),(0,t.jsx)(`div`,{className:n.cardGrid,children:r.map(e=>(0,t.jsxs)(`button`,{className:n.cardItem,onClick:()=>i(`Selected: ${e.title}`),children:[e.image&&(0,t.jsx)(`img`,{src:e.image,alt:e.title,className:n.cardImage}),(0,t.jsxs)(`div`,{className:n.cardBody,children:[(0,t.jsx)(`span`,{className:n.cardTitle,children:e.title}),e.subtitle&&(0,t.jsx)(`span`,{className:n.cardSubtitle,children:e.subtitle}),(0,t.jsxs)(`div`,{className:n.cardMeta,children:[e.price&&(0,t.jsx)(`span`,{className:n.cardPrice,children:e.price}),e.badge&&(0,t.jsx)(`span`,{className:n.cardBadge,children:e.badge})]})]})]},e.id))})]})}function f({title:e,summary:r,actions:i,onSubmit:a}){return(0,t.jsxs)(`div`,{className:n.card,children:[e&&(0,t.jsx)(`p`,{className:n.interactionTitle,children:e}),(0,t.jsx)(`table`,{className:n.confirmSummary,children:(0,t.jsx)(`tbody`,{children:Object.entries(r).map(([e,r])=>(0,t.jsxs)(`tr`,{children:[(0,t.jsx)(`td`,{className:n.confirmKey,children:e}),(0,t.jsx)(`td`,{className:n.confirmVal,children:r})]},e))})}),(0,t.jsx)(`div`,{className:n.confirmActions,children:i.map(e=>(0,t.jsx)(`button`,{className:e.value===`cancel`?n.cancelBtn:n.submitBtn,onClick:()=>a(e.label),children:e.label},e.value))})]})}function p({title:e,steps:r}){return(0,t.jsxs)(`div`,{className:n.card,children:[e&&(0,t.jsx)(`p`,{className:n.interactionTitle,children:e}),(0,t.jsx)(`div`,{className:n.timeline,children:r.map((e,r)=>(0,t.jsxs)(`div`,{className:`${n.timelineStep} ${n[`tl_${e.status}`]}`,children:[(0,t.jsx)(`div`,{className:n.timelineDot}),(0,t.jsxs)(`div`,{className:n.timelineContent,children:[(0,t.jsx)(`span`,{className:n.timelineLabel,children:e.label}),e.timestamp&&(0,t.jsx)(`span`,{className:n.timelineTs,children:e.timestamp})]})]},r))})]})}function m({title:r,slots:i,onSubmit:a}){let[o,s]=(0,e.useState)(null);return(0,t.jsxs)(`div`,{className:n.card,children:[r&&(0,t.jsx)(`p`,{className:n.interactionTitle,children:r}),(0,t.jsx)(`div`,{className:n.slotGrid,children:i.map(e=>(0,t.jsx)(`button`,{className:`${n.slot} ${o===e.id?n.slotActive:``}`,onClick:()=>s(e.id),children:e.label},e.id))}),(0,t.jsx)(`button`,{className:n.submitBtn,onClick:()=>{let e=i.find(e=>e.id===o);e&&a(`Selected slot: ${e.label}${e.datetime?` (${e.datetime})`:``}`)},disabled:!o,children:`Confirm`})]})}function h({title:e,columns:r,rows:i}){return(0,t.jsxs)(`div`,{className:n.card,children:[e&&(0,t.jsx)(`p`,{className:n.interactionTitle,children:e}),(0,t.jsx)(`div`,{className:n.tableWrap,children:(0,t.jsxs)(`table`,{className:n.dataTable,children:[(0,t.jsx)(`thead`,{children:(0,t.jsx)(`tr`,{children:r.map(e=>(0,t.jsx)(`th`,{children:e.label},e.key))})}),(0,t.jsx)(`tbody`,{children:i.map((e,n)=>(0,t.jsx)(`tr`,{children:r.map(n=>(0,t.jsx)(`td`,{children:String(e[n.key]??``)},n.key))},n))})]})})]})}function g({title:r,steps:i,currentStep:a,onSubmit:o}){let[s,c]=(0,e.useState)(a),[l,u]=(0,e.useState)(()=>Object.fromEntries(i.map(e=>[e.id,Object.fromEntries(e.fields.map(e=>[e.key,e.prefilled_value??``]))])));function d(e,t,n){u(r=>({...r,[e]:{...r[e],[t]:n}}))}function f(){let e=i[s];return e.fields.filter(e=>e.required).every(t=>l[e.id]?.[t.key]?.trim())}function p(){let e=[];for(let t of i)for(let n of t.fields){let r=l[t.id]?.[n.key];r?.trim()&&e.push(`${n.label}: ${r}`)}o(e.join(`
3
+ `))}let m=i[s],h=s===i.length-1;return(0,t.jsxs)(`div`,{className:n.card,children:[r&&(0,t.jsx)(`p`,{className:n.interactionTitle,children:r}),(0,t.jsx)(`div`,{className:n.stepperProgress,children:i.map((e,r)=>(0,t.jsx)(`div`,{className:`${n.stepperDot} ${r<s?n.stepperDone:r===s?n.stepperCurrent:``}`},e.id))}),(0,t.jsx)(`p`,{className:n.stepperLabel,children:m.label}),(0,t.jsx)(`div`,{className:n.addressGrid,children:m.fields.map(e=>(0,t.jsxs)(`div`,{className:n.field,children:[(0,t.jsxs)(`label`,{className:n.fieldLabel,children:[e.label,e.required&&(0,t.jsx)(`span`,{className:n.required,children:` *`})]}),(0,t.jsx)(`input`,{className:n.fieldInput,type:e.type===`date_picker`?`date`:e.type,value:l[m.id]?.[e.key]??``,onChange:t=>d(m.id,e.key,t.target.value)})]},e.key))}),(0,t.jsxs)(`div`,{className:n.stepperNav,children:[s>0&&(0,t.jsx)(`button`,{className:n.cancelBtn,onClick:()=>c(e=>e-1),children:`Back`}),h?(0,t.jsx)(`button`,{className:n.submitBtn,onClick:p,disabled:!f(),children:`Submit`}):(0,t.jsx)(`button`,{className:n.submitBtn,onClick:()=>c(e=>e+1),disabled:!f(),children:`Next`})]})]})}exports.ClomRenderer=r;
@@ -0,0 +1,2 @@
1
+ export { ClomRenderer } from './ClomRenderer';
2
+ export type { ClomOutput, InteractionSpec, FormField, InteractionCard, TimelineStep, StepperStep, } from './types';
package/dist/index.js ADDED
@@ -0,0 +1,620 @@
1
+ import { useRef as e, useState as t } from "react";
2
+ import { jsx as n, jsxs as r } from "react/jsx-runtime";
3
+ var i = {
4
+ card: "_card_148uw_16",
5
+ field: "_field_148uw_30",
6
+ fieldLabel: "_fieldLabel_148uw_36",
7
+ required: "_required_148uw_42",
8
+ fieldInput: "_fieldInput_148uw_46",
9
+ fieldTextarea: "_fieldTextarea_148uw_47",
10
+ optionsRow: "_optionsRow_148uw_65",
11
+ optionBtn: "_optionBtn_148uw_71",
12
+ checkList: "_checkList_148uw_89",
13
+ checkItem: "_checkItem_148uw_95",
14
+ checkbox: "_checkbox_148uw_104",
15
+ submitBtn: "_submitBtn_148uw_112",
16
+ interactionTitle: "_interactionTitle_148uw_133",
17
+ hint: "_hint_148uw_140",
18
+ errorText: "_errorText_148uw_146",
19
+ addressGrid: "_addressGrid_148uw_154",
20
+ otpGrid: "_otpGrid_148uw_162",
21
+ otpBox: "_otpBox_148uw_167",
22
+ starRow: "_starRow_148uw_188",
23
+ star: "_star_148uw_188",
24
+ starActive: "_starActive_148uw_205",
25
+ fileZone: "_fileZone_148uw_212",
26
+ fileHint: "_fileHint_148uw_226",
27
+ fileName: "_fileName_148uw_231",
28
+ cardGrid: "_cardGrid_148uw_239",
29
+ cardItem: "_cardItem_148uw_245",
30
+ cardImage: "_cardImage_148uw_265",
31
+ cardBody: "_cardBody_148uw_271",
32
+ cardTitle: "_cardTitle_148uw_278",
33
+ cardSubtitle: "_cardSubtitle_148uw_284",
34
+ cardMeta: "_cardMeta_148uw_289",
35
+ cardPrice: "_cardPrice_148uw_296",
36
+ cardBadge: "_cardBadge_148uw_302",
37
+ confirmSummary: "_confirmSummary_148uw_313",
38
+ confirmKey: "_confirmKey_148uw_319",
39
+ confirmVal: "_confirmVal_148uw_327",
40
+ confirmActions: "_confirmActions_148uw_332",
41
+ cancelBtn: "_cancelBtn_148uw_339",
42
+ timeline: "_timeline_148uw_359",
43
+ timelineStep: "_timelineStep_148uw_365",
44
+ tl_completed: "_tl_completed_148uw_383",
45
+ timelineDot: "_timelineDot_148uw_387",
46
+ tl_active: "_tl_active_148uw_404",
47
+ timelineContent: "_timelineContent_148uw_409",
48
+ timelineLabel: "_timelineLabel_148uw_415",
49
+ tl_pending: "_tl_pending_148uw_421",
50
+ timelineTs: "_timelineTs_148uw_425",
51
+ slotGrid: "_slotGrid_148uw_432",
52
+ slot: "_slot_148uw_432",
53
+ slotActive: "_slotActive_148uw_456",
54
+ tableWrap: "_tableWrap_148uw_464",
55
+ dataTable: "_dataTable_148uw_470",
56
+ stepperProgress: "_stepperProgress_148uw_498",
57
+ stepperDot: "_stepperDot_148uw_505",
58
+ stepperDone: "_stepperDone_148uw_513",
59
+ stepperCurrent: "_stepperCurrent_148uw_517",
60
+ stepperLabel: "_stepperLabel_148uw_523",
61
+ stepperNav: "_stepperNav_148uw_530"
62
+ };
63
+ //#endregion
64
+ //#region src/ClomRenderer.tsx
65
+ function a({ data: e, onSubmit: t, locked: r }) {
66
+ if (r) return null;
67
+ let i = e;
68
+ switch (i.interaction) {
69
+ case "form": return /* @__PURE__ */ n(o, {
70
+ title: i.title,
71
+ fields: i.fields,
72
+ onSubmit: t
73
+ });
74
+ case "address": return /* @__PURE__ */ n(o, {
75
+ title: i.title ?? "Delivery Address",
76
+ fields: i.fields,
77
+ onSubmit: t
78
+ });
79
+ case "select": return /* @__PURE__ */ n(s, {
80
+ options: i.options,
81
+ onSubmit: t
82
+ });
83
+ case "multiselect": return /* @__PURE__ */ n(c, {
84
+ options: i.options,
85
+ onSubmit: t
86
+ });
87
+ case "date_picker": return /* @__PURE__ */ n(l, {
88
+ label: i.label,
89
+ minDate: i.min_date,
90
+ maxDate: i.max_date,
91
+ onSubmit: t
92
+ });
93
+ case "otp": return /* @__PURE__ */ n(u, {
94
+ label: i.label,
95
+ length: i.length ?? 6,
96
+ hint: i.hint,
97
+ onSubmit: t
98
+ });
99
+ case "rating": return /* @__PURE__ */ n(d, {
100
+ label: i.label,
101
+ max: i.max ?? 5,
102
+ labels: i.labels,
103
+ onSubmit: t
104
+ });
105
+ case "file_upload": return /* @__PURE__ */ n(f, {
106
+ label: i.label,
107
+ accept: i.accept,
108
+ maxMb: i.max_mb ?? 10,
109
+ onSubmit: t
110
+ });
111
+ case "card_grid": return /* @__PURE__ */ n(p, {
112
+ title: i.title,
113
+ cards: i.cards,
114
+ onSubmit: t
115
+ });
116
+ case "confirmation_card": return /* @__PURE__ */ n(m, {
117
+ title: i.title,
118
+ summary: i.summary,
119
+ actions: i.actions,
120
+ onSubmit: t
121
+ });
122
+ case "timeline": return /* @__PURE__ */ n(h, {
123
+ title: i.title,
124
+ steps: i.steps
125
+ });
126
+ case "slot_picker": return /* @__PURE__ */ n(g, {
127
+ title: i.title,
128
+ slots: i.slots,
129
+ onSubmit: t
130
+ });
131
+ case "data_table": return /* @__PURE__ */ n(_, {
132
+ title: i.title,
133
+ columns: i.columns,
134
+ rows: i.rows
135
+ });
136
+ case "stepper": return /* @__PURE__ */ n(v, {
137
+ title: i.title,
138
+ steps: i.steps,
139
+ currentStep: i.current_step,
140
+ onSubmit: t
141
+ });
142
+ default: return null;
143
+ }
144
+ }
145
+ function o({ title: e, fields: a, onSubmit: o }) {
146
+ let [s, c] = t(() => Object.fromEntries(a.map((e) => [e.key, e.prefilled_value ?? ""])));
147
+ function l() {
148
+ let e = a.map((e) => `${e.label}: ${s[e.key] ?? ""}`).filter((e, t) => s[a[t].key]?.trim());
149
+ e.length !== 0 && o(e.join("\n"));
150
+ }
151
+ let u = a.filter((e) => e.required).every((e) => s[e.key]?.trim());
152
+ return /* @__PURE__ */ r("div", {
153
+ className: i.card,
154
+ children: [
155
+ e && /* @__PURE__ */ n("p", {
156
+ className: i.interactionTitle,
157
+ children: e
158
+ }),
159
+ /* @__PURE__ */ n("div", {
160
+ className: i.addressGrid,
161
+ children: a.map((e) => /* @__PURE__ */ r("div", {
162
+ className: i.field,
163
+ children: [/* @__PURE__ */ r("label", {
164
+ className: i.fieldLabel,
165
+ children: [e.label, e.required && /* @__PURE__ */ n("span", {
166
+ className: i.required,
167
+ children: " *"
168
+ })]
169
+ }), e.type === "textarea" ? /* @__PURE__ */ n("textarea", {
170
+ className: i.fieldTextarea,
171
+ rows: 3,
172
+ value: s[e.key] ?? "",
173
+ onChange: (t) => c((n) => ({
174
+ ...n,
175
+ [e.key]: t.target.value
176
+ }))
177
+ }) : /* @__PURE__ */ n("input", {
178
+ className: i.fieldInput,
179
+ type: e.type === "date_picker" ? "date" : e.type === "file_upload" ? "file" : e.type,
180
+ value: s[e.key] ?? "",
181
+ onChange: (t) => c((n) => ({
182
+ ...n,
183
+ [e.key]: t.target.value
184
+ }))
185
+ })]
186
+ }, e.key))
187
+ }),
188
+ /* @__PURE__ */ n("button", {
189
+ className: i.submitBtn,
190
+ onClick: l,
191
+ disabled: !u,
192
+ children: "Send"
193
+ })
194
+ ]
195
+ });
196
+ }
197
+ function s({ options: e, onSubmit: t }) {
198
+ return /* @__PURE__ */ n("div", {
199
+ className: i.card,
200
+ children: /* @__PURE__ */ n("div", {
201
+ className: i.optionsRow,
202
+ children: e.map((e) => /* @__PURE__ */ n("button", {
203
+ className: i.optionBtn,
204
+ onClick: () => t(e),
205
+ children: e
206
+ }, e))
207
+ })
208
+ });
209
+ }
210
+ function c({ options: e, onSubmit: a }) {
211
+ let [o, s] = t(/* @__PURE__ */ new Set());
212
+ function c(e) {
213
+ s((t) => {
214
+ let n = new Set(t);
215
+ return n.has(e) ? n.delete(e) : n.add(e), n;
216
+ });
217
+ }
218
+ return /* @__PURE__ */ r("div", {
219
+ className: i.card,
220
+ children: [/* @__PURE__ */ n("div", {
221
+ className: i.checkList,
222
+ children: e.map((e) => /* @__PURE__ */ r("label", {
223
+ className: i.checkItem,
224
+ children: [/* @__PURE__ */ n("input", {
225
+ type: "checkbox",
226
+ checked: o.has(e),
227
+ onChange: () => c(e),
228
+ className: i.checkbox
229
+ }), e]
230
+ }, e))
231
+ }), /* @__PURE__ */ n("button", {
232
+ className: i.submitBtn,
233
+ onClick: () => a([...o].join(", ")),
234
+ disabled: o.size === 0,
235
+ children: "Confirm"
236
+ })]
237
+ });
238
+ }
239
+ function l({ label: e, minDate: a, maxDate: o, onSubmit: s }) {
240
+ let [c, l] = t("");
241
+ return /* @__PURE__ */ r("div", {
242
+ className: i.card,
243
+ children: [
244
+ /* @__PURE__ */ n("label", {
245
+ className: i.fieldLabel,
246
+ children: e
247
+ }),
248
+ /* @__PURE__ */ n("input", {
249
+ type: "date",
250
+ className: i.fieldInput,
251
+ value: c,
252
+ min: a,
253
+ max: o,
254
+ onChange: (e) => l(e.target.value)
255
+ }),
256
+ /* @__PURE__ */ n("button", {
257
+ className: i.submitBtn,
258
+ onClick: () => s(`${e}: ${c}`),
259
+ disabled: !c,
260
+ children: "Confirm"
261
+ })
262
+ ]
263
+ });
264
+ }
265
+ function u({ label: a, length: o, hint: s, onSubmit: c }) {
266
+ let [l, u] = t(Array(o).fill("")), d = e([]);
267
+ function f(e, t) {
268
+ let n = t.replace(/\D/g, "").slice(-1), r = [...l];
269
+ r[e] = n, u(r), n && e < o - 1 && d.current[e + 1]?.focus();
270
+ }
271
+ function p(e, t) {
272
+ t.key === "Backspace" && !l[e] && e > 0 && d.current[e - 1]?.focus();
273
+ }
274
+ function m(e) {
275
+ let t = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, o);
276
+ t.length > 0 && (u([...t.split(""), ...Array(o - t.length).fill("")]), d.current[Math.min(t.length, o - 1)]?.focus()), e.preventDefault();
277
+ }
278
+ let h = l.join("");
279
+ return /* @__PURE__ */ r("div", {
280
+ className: i.card,
281
+ children: [
282
+ /* @__PURE__ */ n("p", {
283
+ className: i.fieldLabel,
284
+ children: a
285
+ }),
286
+ s && /* @__PURE__ */ n("p", {
287
+ className: i.hint,
288
+ children: s
289
+ }),
290
+ /* @__PURE__ */ n("div", {
291
+ className: i.otpGrid,
292
+ onPaste: m,
293
+ children: l.map((e, t) => /* @__PURE__ */ n("input", {
294
+ ref: (e) => {
295
+ d.current[t] = e;
296
+ },
297
+ className: i.otpBox,
298
+ type: "text",
299
+ inputMode: "numeric",
300
+ maxLength: 1,
301
+ value: e,
302
+ onChange: (e) => f(t, e.target.value),
303
+ onKeyDown: (e) => p(t, e)
304
+ }, t))
305
+ }),
306
+ /* @__PURE__ */ n("button", {
307
+ className: i.submitBtn,
308
+ onClick: () => c(`${a}: ${h}`),
309
+ disabled: h.length < o,
310
+ children: "Verify"
311
+ })
312
+ ]
313
+ });
314
+ }
315
+ function d({ label: e, max: a, labels: o, onSubmit: s }) {
316
+ let [c, l] = t(0), [u, d] = t(0);
317
+ function f(t) {
318
+ d(t), s(`${e}: ${t}/${a}${o?.[t - 1] ? ` (${o[t - 1]})` : ""}`);
319
+ }
320
+ return /* @__PURE__ */ r("div", {
321
+ className: i.card,
322
+ children: [
323
+ /* @__PURE__ */ n("p", {
324
+ className: i.fieldLabel,
325
+ children: e
326
+ }),
327
+ /* @__PURE__ */ n("div", {
328
+ className: i.starRow,
329
+ children: Array.from({ length: a }, (e, t) => t + 1).map((e) => /* @__PURE__ */ n("button", {
330
+ className: `${i.star} ${e <= (c || u) ? i.starActive : ""}`,
331
+ onMouseEnter: () => l(e),
332
+ onMouseLeave: () => l(0),
333
+ onClick: () => f(e),
334
+ "aria-label": `${e} star${e === 1 ? "" : "s"}`,
335
+ children: "★"
336
+ }, e))
337
+ }),
338
+ o && c > 0 && /* @__PURE__ */ n("p", {
339
+ className: i.hint,
340
+ children: o[c - 1]
341
+ })
342
+ ]
343
+ });
344
+ }
345
+ function f({ label: a, accept: o, maxMb: s, onSubmit: c }) {
346
+ let [l, u] = t(null), [d, f] = t(null), p = e(null);
347
+ function m(e) {
348
+ if (e.size > s * 1024 * 1024) {
349
+ f(`File must be under ${s} MB`);
350
+ return;
351
+ }
352
+ f(null), u(e.name);
353
+ }
354
+ function h(e) {
355
+ let t = e.target.files?.[0];
356
+ t && m(t);
357
+ }
358
+ function g(e) {
359
+ e.preventDefault();
360
+ let t = e.dataTransfer.files?.[0];
361
+ t && m(t);
362
+ }
363
+ return /* @__PURE__ */ r("div", {
364
+ className: i.card,
365
+ children: [
366
+ /* @__PURE__ */ n("p", {
367
+ className: i.fieldLabel,
368
+ children: a
369
+ }),
370
+ /* @__PURE__ */ r("div", {
371
+ className: i.fileZone,
372
+ onClick: () => p.current?.click(),
373
+ onDragOver: (e) => e.preventDefault(),
374
+ onDrop: g,
375
+ children: [/* @__PURE__ */ n("input", {
376
+ ref: p,
377
+ type: "file",
378
+ accept: o,
379
+ style: { display: "none" },
380
+ onChange: h
381
+ }), l ? /* @__PURE__ */ n("span", {
382
+ className: i.fileName,
383
+ children: l
384
+ }) : /* @__PURE__ */ n("span", {
385
+ className: i.fileHint,
386
+ children: "Tap to choose or drag a file here"
387
+ })]
388
+ }),
389
+ d && /* @__PURE__ */ n("p", {
390
+ className: i.errorText,
391
+ children: d
392
+ }),
393
+ /* @__PURE__ */ n("button", {
394
+ className: i.submitBtn,
395
+ onClick: () => c(`${a}: ${l}`),
396
+ disabled: !l,
397
+ children: "Upload"
398
+ })
399
+ ]
400
+ });
401
+ }
402
+ function p({ title: e, cards: t, onSubmit: a }) {
403
+ return /* @__PURE__ */ r("div", {
404
+ className: i.card,
405
+ children: [e && /* @__PURE__ */ n("p", {
406
+ className: i.interactionTitle,
407
+ children: e
408
+ }), /* @__PURE__ */ n("div", {
409
+ className: i.cardGrid,
410
+ children: t.map((e) => /* @__PURE__ */ r("button", {
411
+ className: i.cardItem,
412
+ onClick: () => a(`Selected: ${e.title}`),
413
+ children: [e.image && /* @__PURE__ */ n("img", {
414
+ src: e.image,
415
+ alt: e.title,
416
+ className: i.cardImage
417
+ }), /* @__PURE__ */ r("div", {
418
+ className: i.cardBody,
419
+ children: [
420
+ /* @__PURE__ */ n("span", {
421
+ className: i.cardTitle,
422
+ children: e.title
423
+ }),
424
+ e.subtitle && /* @__PURE__ */ n("span", {
425
+ className: i.cardSubtitle,
426
+ children: e.subtitle
427
+ }),
428
+ /* @__PURE__ */ r("div", {
429
+ className: i.cardMeta,
430
+ children: [e.price && /* @__PURE__ */ n("span", {
431
+ className: i.cardPrice,
432
+ children: e.price
433
+ }), e.badge && /* @__PURE__ */ n("span", {
434
+ className: i.cardBadge,
435
+ children: e.badge
436
+ })]
437
+ })
438
+ ]
439
+ })]
440
+ }, e.id))
441
+ })]
442
+ });
443
+ }
444
+ function m({ title: e, summary: t, actions: a, onSubmit: o }) {
445
+ return /* @__PURE__ */ r("div", {
446
+ className: i.card,
447
+ children: [
448
+ e && /* @__PURE__ */ n("p", {
449
+ className: i.interactionTitle,
450
+ children: e
451
+ }),
452
+ /* @__PURE__ */ n("table", {
453
+ className: i.confirmSummary,
454
+ children: /* @__PURE__ */ n("tbody", { children: Object.entries(t).map(([e, t]) => /* @__PURE__ */ r("tr", { children: [/* @__PURE__ */ n("td", {
455
+ className: i.confirmKey,
456
+ children: e
457
+ }), /* @__PURE__ */ n("td", {
458
+ className: i.confirmVal,
459
+ children: t
460
+ })] }, e)) })
461
+ }),
462
+ /* @__PURE__ */ n("div", {
463
+ className: i.confirmActions,
464
+ children: a.map((e) => /* @__PURE__ */ n("button", {
465
+ className: e.value === "cancel" ? i.cancelBtn : i.submitBtn,
466
+ onClick: () => o(e.label),
467
+ children: e.label
468
+ }, e.value))
469
+ })
470
+ ]
471
+ });
472
+ }
473
+ function h({ title: e, steps: t }) {
474
+ return /* @__PURE__ */ r("div", {
475
+ className: i.card,
476
+ children: [e && /* @__PURE__ */ n("p", {
477
+ className: i.interactionTitle,
478
+ children: e
479
+ }), /* @__PURE__ */ n("div", {
480
+ className: i.timeline,
481
+ children: t.map((e, t) => /* @__PURE__ */ r("div", {
482
+ className: `${i.timelineStep} ${i[`tl_${e.status}`]}`,
483
+ children: [/* @__PURE__ */ n("div", { className: i.timelineDot }), /* @__PURE__ */ r("div", {
484
+ className: i.timelineContent,
485
+ children: [/* @__PURE__ */ n("span", {
486
+ className: i.timelineLabel,
487
+ children: e.label
488
+ }), e.timestamp && /* @__PURE__ */ n("span", {
489
+ className: i.timelineTs,
490
+ children: e.timestamp
491
+ })]
492
+ })]
493
+ }, t))
494
+ })]
495
+ });
496
+ }
497
+ function g({ title: e, slots: a, onSubmit: o }) {
498
+ let [s, c] = t(null);
499
+ return /* @__PURE__ */ r("div", {
500
+ className: i.card,
501
+ children: [
502
+ e && /* @__PURE__ */ n("p", {
503
+ className: i.interactionTitle,
504
+ children: e
505
+ }),
506
+ /* @__PURE__ */ n("div", {
507
+ className: i.slotGrid,
508
+ children: a.map((e) => /* @__PURE__ */ n("button", {
509
+ className: `${i.slot} ${s === e.id ? i.slotActive : ""}`,
510
+ onClick: () => c(e.id),
511
+ children: e.label
512
+ }, e.id))
513
+ }),
514
+ /* @__PURE__ */ n("button", {
515
+ className: i.submitBtn,
516
+ onClick: () => {
517
+ let e = a.find((e) => e.id === s);
518
+ e && o(`Selected slot: ${e.label}${e.datetime ? ` (${e.datetime})` : ""}`);
519
+ },
520
+ disabled: !s,
521
+ children: "Confirm"
522
+ })
523
+ ]
524
+ });
525
+ }
526
+ function _({ title: e, columns: t, rows: a }) {
527
+ return /* @__PURE__ */ r("div", {
528
+ className: i.card,
529
+ children: [e && /* @__PURE__ */ n("p", {
530
+ className: i.interactionTitle,
531
+ children: e
532
+ }), /* @__PURE__ */ n("div", {
533
+ className: i.tableWrap,
534
+ children: /* @__PURE__ */ r("table", {
535
+ className: i.dataTable,
536
+ children: [/* @__PURE__ */ n("thead", { children: /* @__PURE__ */ n("tr", { children: t.map((e) => /* @__PURE__ */ n("th", { children: e.label }, e.key)) }) }), /* @__PURE__ */ n("tbody", { children: a.map((e, r) => /* @__PURE__ */ n("tr", { children: t.map((t) => /* @__PURE__ */ n("td", { children: String(e[t.key] ?? "") }, t.key)) }, r)) })]
537
+ })
538
+ })]
539
+ });
540
+ }
541
+ function v({ title: e, steps: a, currentStep: o, onSubmit: s }) {
542
+ let [c, l] = t(o), [u, d] = t(() => Object.fromEntries(a.map((e) => [e.id, Object.fromEntries(e.fields.map((e) => [e.key, e.prefilled_value ?? ""]))])));
543
+ function f(e, t, n) {
544
+ d((r) => ({
545
+ ...r,
546
+ [e]: {
547
+ ...r[e],
548
+ [t]: n
549
+ }
550
+ }));
551
+ }
552
+ function p() {
553
+ let e = a[c];
554
+ return e.fields.filter((e) => e.required).every((t) => u[e.id]?.[t.key]?.trim());
555
+ }
556
+ function m() {
557
+ let e = [];
558
+ for (let t of a) for (let n of t.fields) {
559
+ let r = u[t.id]?.[n.key];
560
+ r?.trim() && e.push(`${n.label}: ${r}`);
561
+ }
562
+ s(e.join("\n"));
563
+ }
564
+ let h = a[c], g = c === a.length - 1;
565
+ return /* @__PURE__ */ r("div", {
566
+ className: i.card,
567
+ children: [
568
+ e && /* @__PURE__ */ n("p", {
569
+ className: i.interactionTitle,
570
+ children: e
571
+ }),
572
+ /* @__PURE__ */ n("div", {
573
+ className: i.stepperProgress,
574
+ children: a.map((e, t) => /* @__PURE__ */ n("div", { className: `${i.stepperDot} ${t < c ? i.stepperDone : t === c ? i.stepperCurrent : ""}` }, e.id))
575
+ }),
576
+ /* @__PURE__ */ n("p", {
577
+ className: i.stepperLabel,
578
+ children: h.label
579
+ }),
580
+ /* @__PURE__ */ n("div", {
581
+ className: i.addressGrid,
582
+ children: h.fields.map((e) => /* @__PURE__ */ r("div", {
583
+ className: i.field,
584
+ children: [/* @__PURE__ */ r("label", {
585
+ className: i.fieldLabel,
586
+ children: [e.label, e.required && /* @__PURE__ */ n("span", {
587
+ className: i.required,
588
+ children: " *"
589
+ })]
590
+ }), /* @__PURE__ */ n("input", {
591
+ className: i.fieldInput,
592
+ type: e.type === "date_picker" ? "date" : e.type,
593
+ value: u[h.id]?.[e.key] ?? "",
594
+ onChange: (t) => f(h.id, e.key, t.target.value)
595
+ })]
596
+ }, e.key))
597
+ }),
598
+ /* @__PURE__ */ r("div", {
599
+ className: i.stepperNav,
600
+ children: [c > 0 && /* @__PURE__ */ n("button", {
601
+ className: i.cancelBtn,
602
+ onClick: () => l((e) => e - 1),
603
+ children: "Back"
604
+ }), g ? /* @__PURE__ */ n("button", {
605
+ className: i.submitBtn,
606
+ onClick: m,
607
+ disabled: !p(),
608
+ children: "Submit"
609
+ }) : /* @__PURE__ */ n("button", {
610
+ className: i.submitBtn,
611
+ onClick: () => l((e) => e + 1),
612
+ disabled: !p(),
613
+ children: "Next"
614
+ })]
615
+ })
616
+ ]
617
+ });
618
+ }
619
+ //#endregion
620
+ export { a as ClomRenderer };
package/dist/style.css ADDED
@@ -0,0 +1,2 @@
1
+ :root{--clom-bg:var(--bg,#0f0f13);--clom-surface:var(--surface,#1a1a24);--clom-border:var(--border,#2a2a3a);--clom-text:var(--text,#e8e8f0);--clom-text-muted:var(--text-muted,#7a7a9a);--clom-accent:var(--accent,#6366f1);--clom-accent2:var(--accent2,#8b5cf6)}._card_148uw_16{background:var(--clom-surface);border:1.5px solid var(--clom-border);border-radius:4px 1rem 1rem;flex-direction:column;align-self:flex-start;gap:.625rem;max-width:min(85%,420px);margin-top:-.25rem;padding:.875rem;display:flex}._field_148uw_30{flex-direction:column;gap:.25rem;display:flex}._fieldLabel_148uw_36{color:var(--clom-text-muted);font-size:.8125rem;font-weight:500}._required_148uw_42{color:var(--clom-accent)}._fieldInput_148uw_46,._fieldTextarea_148uw_47{border:1.5px solid var(--clom-border);background:var(--clom-bg);color:var(--clom-text);resize:vertical;border-radius:.625rem;outline:none;padding:.5rem .75rem;font-family:inherit;font-size:.9rem;transition:border-color .15s}._fieldInput_148uw_46:focus,._fieldTextarea_148uw_47:focus{border-color:var(--clom-accent)}._optionsRow_148uw_65{flex-wrap:wrap;gap:.5rem;display:flex}._optionBtn_148uw_71{border:1.5px solid var(--clom-accent);color:var(--clom-accent);cursor:pointer;background:0 0;border-radius:9999px;padding:.4rem .875rem;font-family:inherit;font-size:.875rem;font-weight:500;transition:background .15s,color .15s}._optionBtn_148uw_71:hover{background:var(--clom-accent);color:#fff}._checkList_148uw_89{flex-direction:column;gap:.375rem;display:flex}._checkItem_148uw_95{cursor:pointer;color:var(--clom-text);align-items:center;gap:.5rem;font-size:.9rem;display:flex}._checkbox_148uw_104{accent-color:var(--clom-accent);cursor:pointer;flex-shrink:0;width:16px;height:16px}._submitBtn_148uw_112{background:linear-gradient(135deg, var(--clom-accent), var(--clom-accent2));color:#fff;cursor:pointer;border:none;border-radius:9999px;align-self:flex-end;padding:.5rem 1.5rem;font-family:inherit;font-size:.875rem;font-weight:600;transition:opacity .15s}._submitBtn_148uw_112:disabled{opacity:.45;cursor:not-allowed}._interactionTitle_148uw_133{color:var(--clom-text);margin:0 0 .25rem;font-size:.875rem;font-weight:600}._hint_148uw_140{color:var(--clom-text-muted);margin:0;font-size:.8rem}._errorText_148uw_146{color:#ef4444;margin:0;font-size:.8rem}._addressGrid_148uw_154{flex-direction:column;gap:.5rem;display:flex}._otpGrid_148uw_162{gap:.4rem;display:flex}._otpBox_148uw_167{text-align:center;border:1.5px solid var(--clom-border);background:var(--clom-bg);width:2.4rem;height:2.8rem;color:var(--clom-text);border-radius:.5rem;outline:none;font-family:inherit;font-size:1.125rem;font-weight:600;transition:border-color .15s}._otpBox_148uw_167:focus{border-color:var(--clom-accent)}._starRow_148uw_188{gap:.25rem;display:flex}._star_148uw_188{cursor:pointer;color:var(--clom-border);background:0 0;border:none;padding:0;font-size:1.75rem;line-height:1;transition:color .1s,transform .1s}._star_148uw_188:hover,._starActive_148uw_205{color:#f59e0b;transform:scale(1.15)}._fileZone_148uw_212{border:1.5px dashed var(--clom-border);text-align:center;cursor:pointer;border-radius:.75rem;padding:1.25rem 1rem;transition:border-color .15s,background .15s}._fileZone_148uw_212:hover{border-color:var(--clom-accent);background:color-mix(in srgb, var(--clom-accent) 5%, transparent)}._fileHint_148uw_226{color:var(--clom-text-muted);font-size:.85rem}._fileName_148uw_231{color:var(--clom-accent);font-size:.85rem;font-weight:500}._cardGrid_148uw_239{grid-template-columns:repeat(auto-fill,minmax(130px,1fr));gap:.5rem;display:grid}._cardItem_148uw_245{background:var(--clom-bg);border:1.5px solid var(--clom-border);cursor:pointer;text-align:left;border-radius:.75rem;flex-direction:column;align-items:flex-start;padding:0;font-family:inherit;transition:border-color .15s,box-shadow .15s;display:flex;overflow:hidden}._cardItem_148uw_245:hover{border-color:var(--clom-accent);box-shadow:0 0 0 2px color-mix(in srgb, var(--clom-accent) 20%, transparent)}._cardImage_148uw_265{aspect-ratio:4/3;object-fit:cover;width:100%}._cardBody_148uw_271{flex-direction:column;gap:.2rem;padding:.5rem;display:flex}._cardTitle_148uw_278{color:var(--clom-text);font-size:.85rem;font-weight:600}._cardSubtitle_148uw_284{color:var(--clom-text-muted);font-size:.775rem}._cardMeta_148uw_289{align-items:center;gap:.375rem;margin-top:.125rem;display:flex}._cardPrice_148uw_296{color:var(--clom-accent);font-size:.8rem;font-weight:600}._cardBadge_148uw_302{background:color-mix(in srgb, var(--clom-accent) 15%, transparent);color:var(--clom-accent);border-radius:9999px;padding:.1rem .4rem;font-size:.7rem;font-weight:500}._confirmSummary_148uw_313{border-collapse:collapse;width:100%;font-size:.875rem}._confirmKey_148uw_319{color:var(--clom-text-muted);vertical-align:top;white-space:nowrap;padding:.25rem .5rem .25rem 0;font-weight:500}._confirmVal_148uw_327{color:var(--clom-text);padding:.25rem 0}._confirmActions_148uw_332{justify-content:flex-end;gap:.5rem;margin-top:.25rem;display:flex}._cancelBtn_148uw_339{border:1.5px solid var(--clom-border);color:var(--clom-text-muted);cursor:pointer;background:0 0;border-radius:9999px;padding:.5rem 1.25rem;font-family:inherit;font-size:.875rem;font-weight:600;transition:border-color .15s,color .15s}._cancelBtn_148uw_339:hover{border-color:var(--clom-text-muted);color:var(--clom-text)}._timeline_148uw_359{flex-direction:column;gap:0;display:flex}._timelineStep_148uw_365{align-items:flex-start;gap:.625rem;padding-bottom:.75rem;display:flex;position:relative}._timelineStep_148uw_365:not(:last-child):after{content:"";background:var(--clom-border);width:2px;position:absolute;top:16px;bottom:0;left:7px}._timelineStep_148uw_365._tl_completed_148uw_383:after{background:var(--clom-accent)}._timelineDot_148uw_387{border:2px solid var(--clom-border);background:var(--clom-bg);z-index:1;border-radius:50%;flex-shrink:0;width:16px;height:16px;margin-top:1px;position:relative}._tl_completed_148uw_383 ._timelineDot_148uw_387{background:var(--clom-accent);border-color:var(--clom-accent)}._tl_active_148uw_404 ._timelineDot_148uw_387{border-color:var(--clom-accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--clom-accent) 20%, transparent)}._timelineContent_148uw_409{flex-direction:column;gap:.1rem;display:flex}._timelineLabel_148uw_415{color:var(--clom-text);font-size:.875rem;font-weight:500}._tl_pending_148uw_421 ._timelineLabel_148uw_415{color:var(--clom-text-muted)}._timelineTs_148uw_425{color:var(--clom-text-muted);font-size:.75rem}._slotGrid_148uw_432{grid-template-columns:repeat(auto-fill,minmax(90px,1fr));gap:.4rem;display:grid}._slot_148uw_432{border:1.5px solid var(--clom-border);background:var(--clom-bg);color:var(--clom-text);cursor:pointer;text-align:center;border-radius:.5rem;padding:.45rem .5rem;font-family:inherit;font-size:.825rem;font-weight:500;transition:border-color .15s,background .15s,color .15s}._slot_148uw_432:hover{border-color:var(--clom-accent)}._slotActive_148uw_456{border-color:var(--clom-accent);background:color-mix(in srgb, var(--clom-accent) 12%, transparent);color:var(--clom-accent)}._tableWrap_148uw_464{border:1.5px solid var(--clom-border);border-radius:.5rem;overflow-x:auto}._dataTable_148uw_470{border-collapse:collapse;width:100%;font-size:.825rem}._dataTable_148uw_470 th{background:var(--clom-surface);color:var(--clom-text-muted);text-align:left;border-bottom:1px solid var(--clom-border);white-space:nowrap;padding:.4rem .625rem;font-weight:600}._dataTable_148uw_470 td{color:var(--clom-text);border-bottom:1px solid var(--clom-border);padding:.35rem .625rem}._dataTable_148uw_470 tr:last-child td{border-bottom:none}._stepperProgress_148uw_498{align-items:center;gap:.375rem;margin-bottom:.25rem;display:flex}._stepperDot_148uw_505{background:var(--clom-border);border-radius:50%;width:8px;height:8px;transition:background .2s}._stepperDone_148uw_513{background:var(--clom-accent)}._stepperCurrent_148uw_517{background:var(--clom-accent2);border-radius:4px;width:20px}._stepperLabel_148uw_523{color:var(--clom-text-muted);margin:0 0 .25rem;font-size:.8125rem;font-weight:600}._stepperNav_148uw_530{justify-content:flex-end;gap:.5rem;margin-top:.25rem;display:flex}
2
+ /*$vite$:1*/
@@ -0,0 +1,107 @@
1
+ export interface FormField {
2
+ key: string;
3
+ label: string;
4
+ type: "text" | "email" | "tel" | "number" | "textarea" | "date_picker" | "file_upload" | "otp" | "rating";
5
+ required: boolean;
6
+ prefilled_value?: string;
7
+ rating_max?: number;
8
+ otp_length?: number;
9
+ accept?: string;
10
+ }
11
+ export interface InteractionCard {
12
+ id: string;
13
+ title: string;
14
+ subtitle?: string;
15
+ image?: string;
16
+ price?: string;
17
+ badge?: string;
18
+ }
19
+ export interface TimelineStep {
20
+ label: string;
21
+ status: "completed" | "active" | "pending";
22
+ timestamp?: string;
23
+ }
24
+ export interface StepperStep {
25
+ id: string;
26
+ label: string;
27
+ fields: FormField[];
28
+ }
29
+ export type InteractionSpec = {
30
+ interaction: "form";
31
+ title?: string;
32
+ fields: FormField[];
33
+ } | {
34
+ interaction: "select";
35
+ options: string[];
36
+ } | {
37
+ interaction: "multiselect";
38
+ options: string[];
39
+ } | {
40
+ interaction: "address";
41
+ title?: string;
42
+ prefilled?: Record<string, string>;
43
+ fields: FormField[];
44
+ } | {
45
+ interaction: "date_picker";
46
+ label: string;
47
+ min_date?: string;
48
+ max_date?: string;
49
+ } | {
50
+ interaction: "otp";
51
+ label: string;
52
+ length?: number;
53
+ hint?: string;
54
+ } | {
55
+ interaction: "rating";
56
+ label: string;
57
+ max?: number;
58
+ labels?: string[];
59
+ } | {
60
+ interaction: "file_upload";
61
+ label: string;
62
+ accept?: string;
63
+ max_mb?: number;
64
+ } | {
65
+ interaction: "card_grid";
66
+ title?: string;
67
+ cards: InteractionCard[];
68
+ } | {
69
+ interaction: "confirmation_card";
70
+ title?: string;
71
+ summary: Record<string, string>;
72
+ actions: {
73
+ label: string;
74
+ value: string;
75
+ }[];
76
+ } | {
77
+ interaction: "timeline";
78
+ title?: string;
79
+ steps: TimelineStep[];
80
+ } | {
81
+ interaction: "slot_picker";
82
+ title?: string;
83
+ slots: {
84
+ id: string;
85
+ label: string;
86
+ datetime?: string;
87
+ }[];
88
+ date_label?: string;
89
+ } | {
90
+ interaction: "data_table";
91
+ title?: string;
92
+ columns: {
93
+ key: string;
94
+ label: string;
95
+ }[];
96
+ rows: Record<string, unknown>[];
97
+ } | {
98
+ interaction: "stepper";
99
+ title?: string;
100
+ steps: StepperStep[];
101
+ current_step: number;
102
+ };
103
+ /**
104
+ * Raw CLOM output — discriminated by the `interaction` field.
105
+ * Any extra metadata fields CLOM appends are passed through and ignored by the renderer.
106
+ */
107
+ export type ClomOutput = InteractionSpec & Record<string, unknown>;
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "clom-renderer",
3
+ "version": "1.0.0",
4
+ "description": "React component library for rendering CLOM protocol interactions",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs",
13
+ "types": "./dist/index.d.ts"
14
+ },
15
+ "./style.css": "./dist/style.css"
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "build": "vite build",
22
+ "dev": "vite build --watch"
23
+ },
24
+ "peerDependencies": {
25
+ "react": ">=17.0.0",
26
+ "react-dom": ">=17.0.0"
27
+ },
28
+ "devDependencies": {
29
+ "@types/react": "^19.2.14",
30
+ "@types/react-dom": "^19.2.3",
31
+ "@vitejs/plugin-react": "^6.0.1",
32
+ "react": "^19.2.4",
33
+ "react-dom": "^19.2.4",
34
+ "typescript": "~5.9.3",
35
+ "vite": "^8.0.1",
36
+ "vite-plugin-dts": "^4.5.4"
37
+ }
38
+ }