@loworbitstudio/visor 1.30.0 → 1.31.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,6 +1,6 @@
1
1
  {
2
2
  "version": "0.4.0",
3
- "generated_at": "2026-10-03T18:10:41.409Z",
3
+ "generated_at": "2026-10-03T23:23:41.697Z",
4
4
  "components": {
5
5
  "accessibility-specimen": {
6
6
  "changeType": "current",
@@ -14,6 +14,12 @@
14
14
  "breakingChange": false,
15
15
  "migrationNote": null
16
16
  },
17
+ "action-row": {
18
+ "changeType": "current",
19
+ "files": [],
20
+ "breakingChange": false,
21
+ "migrationNote": null
22
+ },
17
23
  "activity-feed": {
18
24
  "changeType": "current",
19
25
  "files": [],
@@ -746,6 +752,12 @@
746
752
  "breakingChange": false,
747
753
  "migrationNote": null
748
754
  },
755
+ "time-picker": {
756
+ "changeType": "current",
757
+ "files": [],
758
+ "breakingChange": false,
759
+ "migrationNote": null
760
+ },
749
761
  "timeline": {
750
762
  "changeType": "current",
751
763
  "files": [],
package/dist/index.js CHANGED
@@ -8802,6 +8802,50 @@ var FIXTURES = {
8802
8802
  ])],
8803
8803
  };
8804
8804
  })()`
8805
+ },
8806
+ // VI-667: bottom-sheet presentation, with the drag handle and a leading back action.
8807
+ sheet: {
8808
+ export: "Dialog",
8809
+ props: `(function () {
8810
+ var h = React.createElement;
8811
+ return {
8812
+ open: true,
8813
+ presentation: "sheet",
8814
+ children: [h(__mod.DialogTrigger, { key: "tr", asChild: true }, h("button", { type: "button" }, "Open")), h(__mod.DialogContent, { key: "c", showHandle: true }, [
8815
+ h(__mod.DialogHeader, { key: "h", back: h(__mod.DialogBack, null) }, [
8816
+ h(__mod.DialogTitle, { key: "t" }, "Set start time"),
8817
+ h(__mod.DialogDescription, { key: "d" }, "Doors open one hour earlier."),
8818
+ ]),
8819
+ h("input", { key: "i", "aria-label": "Start", defaultValue: "21:00", style: { width: "100%", boxSizing: "border-box", padding: "8px" } }),
8820
+ h(__mod.DialogFooter, { key: "f" }, h("button", { type: "button" }, "Save")),
8821
+ ])],
8822
+ };
8823
+ })()`
8824
+ },
8825
+ // VI-667: dialog scoped to one pane (#root) under a scrim; the page outside it is untouched.
8826
+ scoped: {
8827
+ export: "Dialog",
8828
+ props: `(function () {
8829
+ var h = React.createElement;
8830
+ var pane = document.getElementById("root");
8831
+ pane.style.minHeight = "420px";
8832
+ pane.style.position = "relative";
8833
+ pane.style.background = "var(--surface-card, #f3f4f6)";
8834
+ return {
8835
+ open: true,
8836
+ container: pane,
8837
+ children: [
8838
+ h("p", { key: "p", style: { margin: 0, padding: "16px" } }, "Editor pane: stays visible behind the scrim."),
8839
+ h(__mod.DialogContent, { key: "c" }, [
8840
+ h(__mod.DialogHeader, { key: "h", back: h(__mod.DialogBack, null) }, [
8841
+ h(__mod.DialogTitle, { key: "t" }, "Sign back in"),
8842
+ h(__mod.DialogDescription, { key: "d" }, "Your session timed out."),
8843
+ ]),
8844
+ h(__mod.DialogFooter, { key: "f" }, h("button", { type: "button" }, "Continue")),
8845
+ ]),
8846
+ ],
8847
+ };
8848
+ })()`
8805
8849
  }
8806
8850
  },
8807
8851
  popover: {
@@ -8838,6 +8882,49 @@ var FIXTURES = {
8838
8882
  })()`
8839
8883
  }
8840
8884
  },
8885
+ // VI-669: a block, resolved from blocks/. July 2026 with a stay crossing a week
8886
+ // edge, three overlapping spans plus a fourth ("+1"), a colour-token event, a
8887
+ // day mark, and the week detail slot open under the selected day.
8888
+ "month-calendar": {
8889
+ default: {
8890
+ export: "MonthCalendar",
8891
+ props: `(function () {
8892
+ var h = React.createElement;
8893
+ return {
8894
+ month: "2026-07-01",
8895
+ today: "2026-07-09",
8896
+ selectedDate: "2026-07-15",
8897
+ weekStartsOn: 1,
8898
+ onSelectDate: function () {},
8899
+ events: [
8900
+ { id: "berlin", start: "2026-07-02", end: "2026-07-05", title: "Berlin stay", series: 1 },
8901
+ { id: "lisbon", start: "2026-07-13", end: "2026-07-19", title: "Lisbon run", color: "--chart-3" },
8902
+ { id: "paris", start: "2026-07-20", end: "2026-07-22", title: "Paris", series: 4 },
8903
+ { id: "a", start: "2026-07-20", end: "2026-07-21", title: "Studio hold", series: 2 },
8904
+ { id: "b", start: "2026-07-20", end: "2026-07-24", title: "Press week", series: 5 },
8905
+ { id: "c", start: "2026-07-21", end: "2026-07-22", title: "Fourth lane", series: 3 },
8906
+ { id: "gig", date: "2026-07-09", title: "Soundcheck", status: "success", series: 2 },
8907
+ ],
8908
+ renderDayMark: function (day) { return day.date === "2026-07-17" ? "3" : null; },
8909
+ renderWeekDetail: function (week) {
8910
+ return h("div", null, h("strong", null, "Week of " + week.start), h("p", { style: { margin: 0 } }, "Day sheet content sits here."));
8911
+ },
8912
+ };
8913
+ })()`
8914
+ },
8915
+ overlap: {
8916
+ export: "MonthCalendar",
8917
+ props: `{
8918
+ month: "2026-07-01",
8919
+ events: [
8920
+ { id: "a", start: "2026-07-07", end: "2026-07-11", title: "Stay A", series: 1 },
8921
+ { id: "b", start: "2026-07-08", end: "2026-07-12", title: "Stay B", series: 2 },
8922
+ { id: "c", start: "2026-07-09", end: "2026-07-10", title: "Stay C", series: 3 },
8923
+ { id: "d", start: "2026-07-09", end: "2026-07-10", title: "Stay D", series: 4 },
8924
+ ],
8925
+ }`
8926
+ }
8927
+ },
8841
8928
  "stat-card": {
8842
8929
  default: {
8843
8930
  export: "StatCard",
@@ -9029,6 +9116,14 @@ var FIXTURES = {
9029
9116
  default: { export: "Input", interactiveTarget: "input", props: `{ placeholder: "Email address" }` },
9030
9117
  invalid: { export: "Input", interactiveTarget: "input", props: `{ defaultValue: "not-an-email", "aria-invalid": true }` }
9031
9118
  },
9119
+ // VI-624: `default` is the closed field; the popover fixtures render open so the
9120
+ // two-column (24-hour) and three-column (12-hour) anatomy can be inspected.
9121
+ "time-picker": {
9122
+ default: { export: "TimePicker", interactiveTarget: "input", props: `{ "aria-label": "Doors open", hourCycle: 12, minuteStep: 15, defaultValue: "16:00" }` },
9123
+ "popover-24h": { export: "TimePicker", interactiveTarget: "input", props: `{ "aria-label": "Set start", hourCycle: 24, minuteStep: 15, defaultValue: "16:15", open: true }` },
9124
+ "popover-12h": { export: "TimePicker", interactiveTarget: "input", props: `{ "aria-label": "Doors open", hourCycle: 12, minuteStep: 15, defaultValue: "16:15", open: true }` },
9125
+ invalid: { export: "TimePicker", interactiveTarget: "input", props: `{ "aria-label": "Doors open", hourCycle: 12, defaultValue: "16:00", "aria-invalid": true }` }
9126
+ },
9032
9127
  textarea: {
9033
9128
  default: { export: "Textarea", interactiveTarget: "textarea", props: `{ placeholder: "Tell us more" }` },
9034
9129
  invalid: { export: "Textarea", interactiveTarget: "textarea", props: `{ defaultValue: "Too short", "aria-invalid": true }` }
@@ -9055,6 +9150,51 @@ var FIXTURES = {
9055
9150
  checked: { export: "Checkbox", interactiveTarget: "button", props: `{ "aria-label": "Accept", defaultChecked: true }` },
9056
9151
  invalid: { export: "Checkbox", interactiveTarget: "button", props: `{ "aria-label": "Accept", "aria-invalid": true }` }
9057
9152
  },
9153
+ // VI-668: the card variant — icon, title, line; the third level is drawn disabled.
9154
+ "radio-group": {
9155
+ default: {
9156
+ export: "RadioGroup",
9157
+ interactiveTarget: '[role="radio"]',
9158
+ props: `(function () {
9159
+ var h = React.createElement;
9160
+ return {
9161
+ "aria-label": "Size",
9162
+ defaultValue: "medium",
9163
+ style: { width: 320 },
9164
+ children: ["small", "medium", "large"].map(function (v) {
9165
+ return h(__mod.RadioGroupItem, { key: v, value: v, "aria-label": v });
9166
+ }),
9167
+ };
9168
+ })()`
9169
+ },
9170
+ card: {
9171
+ export: "RadioGroup",
9172
+ interactiveTarget: '[role="radio"]',
9173
+ props: `(function () {
9174
+ var h = React.createElement;
9175
+ var icon = function (shapes) {
9176
+ return h("svg", { width: "1em", height: "1em", viewBox: "0 0 24 24", fill: "currentColor" }, shapes);
9177
+ };
9178
+ var levels = [
9179
+ ["just-you", "Just You", "Only you can see this booking.", icon([h("circle", { key: 1, cx: 12, cy: 8, r: 4 }), h("path", { key: 2, d: "M4 21a8 8 0 0 1 16 0Z" })])],
9180
+ ["team", "Your Team", "Everyone on your team can see it.", icon([h("circle", { key: 1, cx: 8, cy: 9, r: 3.5 }), h("circle", { key: 2, cx: 16, cy: 9, r: 3.5 }), h("path", { key: 3, d: "M1 20a7 7 0 0 1 14 0ZM9 20a7 7 0 0 1 14 0Z" })])],
9181
+ ["public", "Public", "Verified bookers only for now.", icon([h("path", { key: 1, d: "M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm0 3a7 7 0 0 1 0 14 7 7 0 0 1 0-14Z", fillRule: "evenodd" })])],
9182
+ ];
9183
+ return {
9184
+ variant: "card",
9185
+ "aria-label": "Visibility",
9186
+ defaultValue: "team",
9187
+ style: { width: 360 },
9188
+ children: levels.map(function (l, i) {
9189
+ return h(__mod.RadioGroupItem, {
9190
+ key: l[0], value: l[0], icon: l[3], title: l[1], description: l[2],
9191
+ disabled: i === 2, "aria-describedby": i === 2 ? "radio-reason" : undefined,
9192
+ });
9193
+ }).concat([h("p", { key: "r", id: "radio-reason", style: { margin: 0, fontSize: 12 } }, "Public needs a verified booking.")]),
9194
+ };
9195
+ })()`
9196
+ }
9197
+ },
9058
9198
  switch: {
9059
9199
  default: { export: "Switch", interactiveTarget: "button", props: `{ "aria-label": "Notifications" }` },
9060
9200
  checked: { export: "Switch", interactiveTarget: "button", props: `{ "aria-label": "Notifications", defaultChecked: true }` },
@@ -9093,13 +9233,37 @@ var FIXTURES = {
9093
9233
  export: "InlineEdit",
9094
9234
  interactiveTarget: "input",
9095
9235
  props: `{ as: "h2", style: { margin: 0, fontSize: "21px", lineHeight: 1.25, fontWeight: 600 }, label: "Section title", value: "Track record", defaultValue: "Untitled section", onCommit: function () {}, defaultEditing: true }`
9236
+ },
9237
+ // VI-677: pencil={false}. The text is the button, so hover/focus drive it.
9238
+ "no-pencil": {
9239
+ export: "InlineEdit",
9240
+ interactiveTarget: "button",
9241
+ props: `{ label: "Rider title", value: "Technical rider", defaultValue: "Rider", onCommit: function () {}, pencil: false }`
9242
+ },
9243
+ "no-pencil-default-value": {
9244
+ export: "InlineEdit",
9245
+ interactiveTarget: "button",
9246
+ props: `{ label: "Rider title", value: "", defaultValue: "Rider", onCommit: function () {}, pencil: false }`
9247
+ },
9248
+ // Descenders and accents must survive the cap-band trim.
9249
+ "no-pencil-glyphs": {
9250
+ export: "InlineEdit",
9251
+ interactiveTarget: "button",
9252
+ props: `{ label: "Rider title", value: "Typography jpq \xC9\xC5\xD1", defaultValue: "Rider", onCommit: function () {}, pencil: false }`
9253
+ },
9254
+ "no-pencil-heading": {
9255
+ export: "InlineEdit",
9256
+ interactiveTarget: "button",
9257
+ props: `{ as: "h2", style: { margin: 0, fontSize: "21px", lineHeight: 1.25, fontWeight: 600 }, label: "Section title", value: "Track record", defaultValue: "Untitled section", onCommit: function () {}, pencil: false }`
9096
9258
  }
9097
9259
  },
9098
- // VI-657: the autosave readout in each state. It draws no edge in any of them.
9260
+ // VI-657/VI-665: the autosave readout in each state, Unsaved as a dot too. It draws no edge in any of them.
9099
9261
  "save-status": {
9100
9262
  default: { export: "SaveStatus", props: `{ status: "saved" }` },
9101
9263
  saving: { export: "SaveStatus", props: `{ status: "saving" }` },
9264
+ syncing: { export: "SaveStatus", props: `{ status: "syncing" }` },
9102
9265
  unsaved: { export: "SaveStatus", props: `{ status: "unsaved" }` },
9266
+ "unsaved-dot": { export: "SaveStatus", props: `{ status: "unsaved", unsavedAs: "dot" }` },
9103
9267
  refused: { export: "SaveStatus", props: `{ status: "refused" }` },
9104
9268
  "refused-retry": { export: "SaveStatus", interactiveTarget: "button", props: `{ status: "refused", onRetry: function () {} }` }
9105
9269
  },
@@ -9123,6 +9287,55 @@ var FIXTURES = {
9123
9287
  default: {
9124
9288
  export: "EmptyState",
9125
9289
  props: `{ heading: "No projects yet", description: "Create a project to get started." }`
9290
+ },
9291
+ error: {
9292
+ export: "EmptyState",
9293
+ props: `{ intent: "error", tone: "subtle", icon: ${ICON_X}, heading: "Could not load the inbox", description: "The request timed out. Check your connection and try again." }`
9294
+ }
9295
+ },
9296
+ // VI-666: ActionRow. Every row is captioned (title = state, line = what it
9297
+ // reads); `edges-off` binds both switches on the list: the resting edge and
9298
+ // the hairline go, the selected state edge and focus stay. `--state hover|focus` drives the
9299
+ // first row.
9300
+ "action-row": {
9301
+ default: {
9302
+ export: "ActionRowList",
9303
+ props: `(function () {
9304
+ var h = React.createElement;
9305
+ var row = function (key, props) {
9306
+ return h(__mod.ActionRow, Object.assign({ key: key, leading: ${ICON_X}, trailing: h("span", null, "Value") }, props), props.title);
9307
+ };
9308
+ return { "aria-label": "States", style: { maxWidth: "420px" }, children: [
9309
+ row("rest", { title: "Rest", line: "no fill, 44px floor" }),
9310
+ row("selected", { title: "Selected", line: "lifted fill + inset edge", selected: true }),
9311
+ row("open", { title: "Open", line: "open fill, aria-expanded", open: true }),
9312
+ row("disabled", { title: "Disabled", line: "disabled opacity", disabled: true }),
9313
+ h(__mod.ActionRow, { key: "bare", trailing: h("span", null, "Review") }, "Title only, trailing value"),
9314
+ h(__mod.ActionRow, { key: "long", leading: ${ICON_X}, line: "A second line that is long enough that it has to wrap onto another line", trailing: h("span", null, "3 suggested") }, "A title long enough that it wraps to a second line at this width"),
9315
+ h(__mod.ActionRow, { key: "glyphs", leading: ${ICON_X}, line: "Descenders jpqgy and accents \xC9\xC5\xD1", trailing: h("span", null, "jpq \xC9\xC5\xD1") }, "Typography jpq \xC9\xC5\xD1"),
9316
+ h(__mod.ActionRow, { key: "link", asChild: true, leading: ${ICON_X}, trailing: h("span", null, "Open") }, h("a", { href: "#billing" }, "Row as a link (asChild)")),
9317
+ ] };
9318
+ })()`
9319
+ },
9320
+ interactive: {
9321
+ export: "ActionRowList",
9322
+ props: `(function () {
9323
+ var h = React.createElement;
9324
+ return { "aria-label": "Interactive", style: { maxWidth: "420px" }, children: [
9325
+ h(__mod.ActionRow, { key: "a", leading: ${ICON_X}, line: "driven by --state", trailing: h("span", null, "Value") }, "First row"),
9326
+ h(__mod.ActionRow, { key: "b", leading: ${ICON_X}, line: "left at rest", trailing: h("span", null, "Value") }, "Second row"),
9327
+ ] };
9328
+ })()`
9329
+ },
9330
+ "edges-off": {
9331
+ export: "ActionRowList",
9332
+ props: `(function () {
9333
+ var h = React.createElement;
9334
+ return { "aria-label": "Edges off", style: { maxWidth: "420px", "--control-edge-width": "0", "--hairline-width": "0" }, children: [
9335
+ h(__mod.ActionRow, { key: "a", leading: ${ICON_X}, line: "edge kept, resting edge off", trailing: h("span", null, "Value"), selected: true }, "Selected"),
9336
+ h(__mod.ActionRow, { key: "b", leading: ${ICON_X}, line: "hairline off", trailing: h("span", null, "Value") }, "Rest"),
9337
+ ] };
9338
+ })()`
9126
9339
  }
9127
9340
  },
9128
9341
  badge: {
@@ -9173,7 +9386,8 @@ function resolveComponentFile(cwd, name) {
9173
9386
  return firstExisting([
9174
9387
  resolve21(cwd, "components", "ui", name, `${name}.tsx`),
9175
9388
  resolve21(cwd, "components", "devtools", name, `${name}.tsx`),
9176
- resolve21(cwd, "components", "ui", name, "index.tsx")
9389
+ resolve21(cwd, "components", "ui", name, "index.tsx"),
9390
+ resolve21(cwd, "blocks", name, `${name}.tsx`)
9177
9391
  ]);
9178
9392
  }
9179
9393
  function resolveThemeCssFile(cwd, slug2) {
@@ -9301,7 +9515,7 @@ async function renderCommand(component, cwd, options) {
9301
9515
  if (!componentFile) {
9302
9516
  fail3(
9303
9517
  "COMPONENT_NOT_FOUND",
9304
- `Component "${component}" not found under components/ui/. Expected components/ui/${component}/${component}.tsx.`
9518
+ `Component "${component}" not found under components/ui/ or blocks/. Expected components/ui/${component}/${component}.tsx or blocks/${component}/${component}.tsx.`
9305
9519
  );
9306
9520
  }
9307
9521
  const themeCssFile = resolveThemeCssFile(cwd, options.theme);