@pilotiq/pilotiq 0.2.0 → 0.3.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.
Files changed (103) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +8 -0
  3. package/CLAUDE.md +1 -1
  4. package/dist/actions/Action.d.ts +25 -0
  5. package/dist/actions/Action.d.ts.map +1 -1
  6. package/dist/actions/Action.js +25 -0
  7. package/dist/actions/Action.js.map +1 -1
  8. package/dist/elements/dispatchForm.d.ts +0 -14
  9. package/dist/elements/dispatchForm.d.ts.map +1 -1
  10. package/dist/elements/dispatchForm.js +28 -0
  11. package/dist/elements/dispatchForm.js.map +1 -1
  12. package/dist/fields/BuilderField.d.ts +27 -1
  13. package/dist/fields/BuilderField.d.ts.map +1 -1
  14. package/dist/fields/BuilderField.js +36 -1
  15. package/dist/fields/BuilderField.js.map +1 -1
  16. package/dist/fields/FileUploadField.d.ts +65 -0
  17. package/dist/fields/FileUploadField.d.ts.map +1 -1
  18. package/dist/fields/FileUploadField.js +72 -0
  19. package/dist/fields/FileUploadField.js.map +1 -1
  20. package/dist/fields/RepeaterField.d.ts +34 -1
  21. package/dist/fields/RepeaterField.d.ts.map +1 -1
  22. package/dist/fields/RepeaterField.js +43 -1
  23. package/dist/fields/RepeaterField.js.map +1 -1
  24. package/dist/fields/RowButton.d.ts +9 -2
  25. package/dist/fields/RowButton.d.ts.map +1 -1
  26. package/dist/fields/TextField.d.ts +106 -0
  27. package/dist/fields/TextField.d.ts.map +1 -1
  28. package/dist/fields/TextField.js +115 -0
  29. package/dist/fields/TextField.js.map +1 -1
  30. package/dist/filters/queryBuilder/Constraint.d.ts +1 -1
  31. package/dist/filters/queryBuilder/Constraint.d.ts.map +1 -1
  32. package/dist/filters/queryBuilder/TextConstraint.d.ts.map +1 -1
  33. package/dist/filters/queryBuilder/TextConstraint.js +2 -3
  34. package/dist/filters/queryBuilder/TextConstraint.js.map +1 -1
  35. package/dist/orm/modelDefaults.d.ts +1 -1
  36. package/dist/orm/modelDefaults.d.ts.map +1 -1
  37. package/dist/react/SchemaRenderer.d.ts.map +1 -1
  38. package/dist/react/SchemaRenderer.js +108 -7
  39. package/dist/react/SchemaRenderer.js.map +1 -1
  40. package/dist/react/fields/BuilderInput.d.ts.map +1 -1
  41. package/dist/react/fields/BuilderInput.js +32 -3
  42. package/dist/react/fields/BuilderInput.js.map +1 -1
  43. package/dist/react/fields/FieldShell.d.ts +9 -1
  44. package/dist/react/fields/FieldShell.d.ts.map +1 -1
  45. package/dist/react/fields/FieldShell.js +4 -3
  46. package/dist/react/fields/FieldShell.js.map +1 -1
  47. package/dist/react/fields/FileUploadInput.d.ts +17 -4
  48. package/dist/react/fields/FileUploadInput.d.ts.map +1 -1
  49. package/dist/react/fields/FileUploadInput.js +204 -25
  50. package/dist/react/fields/FileUploadInput.js.map +1 -1
  51. package/dist/react/fields/RepeaterInput.d.ts.map +1 -1
  52. package/dist/react/fields/RepeaterInput.js +33 -2
  53. package/dist/react/fields/RepeaterInput.js.map +1 -1
  54. package/dist/react/fields/TextLikeInput.d.ts +5 -1
  55. package/dist/react/fields/TextLikeInput.d.ts.map +1 -1
  56. package/dist/react/fields/TextLikeInput.js +17 -2
  57. package/dist/react/fields/TextLikeInput.js.map +1 -1
  58. package/dist/react/fields/rowChromeButton.d.ts +24 -5
  59. package/dist/react/fields/rowChromeButton.d.ts.map +1 -1
  60. package/dist/react/fields/rowChromeButton.js +51 -8
  61. package/dist/react/fields/rowChromeButton.js.map +1 -1
  62. package/dist/react/fields/textInputControls.d.ts +47 -0
  63. package/dist/react/fields/textInputControls.d.ts.map +1 -0
  64. package/dist/react/fields/textInputControls.js +134 -0
  65. package/dist/react/fields/textInputControls.js.map +1 -0
  66. package/dist/routes.d.ts.map +1 -1
  67. package/dist/routes.js +21 -1
  68. package/dist/routes.js.map +1 -1
  69. package/dist/schema/Alert.d.ts +58 -0
  70. package/dist/schema/Alert.d.ts.map +1 -1
  71. package/dist/schema/Alert.js +68 -1
  72. package/dist/schema/Alert.js.map +1 -1
  73. package/dist/schema/resolveSchema.d.ts.map +1 -1
  74. package/dist/schema/resolveSchema.js +32 -0
  75. package/dist/schema/resolveSchema.js.map +1 -1
  76. package/package.json +2 -1
  77. package/src/actions/Action.test.ts +47 -0
  78. package/src/actions/Action.ts +35 -0
  79. package/src/elements/dispatchForm.ts +28 -0
  80. package/src/fields/BuilderField.ts +38 -1
  81. package/src/fields/FileUploadField.test.ts +46 -0
  82. package/src/fields/FileUploadField.ts +90 -2
  83. package/src/fields/RepeaterField.ts +45 -1
  84. package/src/fields/RowButton.test.ts +70 -0
  85. package/src/fields/RowButton.ts +11 -1
  86. package/src/fields/TextField.test.ts +168 -0
  87. package/src/fields/TextField.ts +141 -1
  88. package/src/filters/QueryBuilderFilter.test.ts +18 -0
  89. package/src/filters/queryBuilder/Constraint.ts +1 -1
  90. package/src/filters/queryBuilder/TextConstraint.ts +5 -6
  91. package/src/orm/modelDefaults.ts +1 -1
  92. package/src/react/SchemaRenderer.tsx +222 -14
  93. package/src/react/fields/BuilderInput.tsx +37 -0
  94. package/src/react/fields/FieldShell.tsx +13 -2
  95. package/src/react/fields/FileUploadInput.tsx +516 -85
  96. package/src/react/fields/RepeaterInput.tsx +39 -0
  97. package/src/react/fields/TextLikeInput.tsx +22 -2
  98. package/src/react/fields/rowChromeButton.tsx +102 -6
  99. package/src/react/fields/textInputControls.tsx +238 -0
  100. package/src/routes.ts +21 -1
  101. package/src/schema/Alert.test.ts +46 -0
  102. package/src/schema/Alert.ts +90 -8
  103. package/src/schema/resolveSchema.ts +32 -0
@@ -1,11 +1,24 @@
1
1
  import { Element } from './Element.js'
2
2
  import type { Action } from '../actions/Action.js'
3
+ import type { IconColor } from './Icon.js'
3
4
 
4
5
  export type AlertType = 'info' | 'warning' | 'success' | 'danger'
5
6
 
7
+ /**
8
+ * Alignment for the footer-actions row inside an `Alert` (Filament v5
9
+ * parity). `'start'` aligns the buttons to the leading edge (LTR =
10
+ * left), `'center'` to the middle, `'end'` to the trailing edge (LTR =
11
+ * right). Defaults to `'start'`.
12
+ */
13
+ export type AlertActionsAlignment = 'start' | 'center' | 'end'
14
+
6
15
  export class Alert extends Element {
7
- private _alertType: AlertType = 'info'
8
- private _title?: string
16
+ private _alertType: AlertType = 'info'
17
+ private _title?: string
18
+ private _dismissible = false
19
+ private _persistKey?: string
20
+ private _iconColor?: IconColor
21
+ private _actionsAlignment: AlertActionsAlignment = 'start'
9
22
 
10
23
  private constructor(private content: string) {
11
24
  super()
@@ -16,12 +29,12 @@ export class Alert extends Element {
16
29
  }
17
30
 
18
31
  alertType(t: AlertType): this { this._alertType = t; return this }
19
- title(t: string): this { this._title = t; return this }
32
+ title(t: string): this { this._title = t; return this }
20
33
 
21
- info(): this { return this.alertType('info') }
34
+ info(): this { return this.alertType('info') }
22
35
  warning(): this { return this.alertType('warning') }
23
36
  success(): this { return this.alertType('success') }
24
- danger(): this { return this.alertType('danger') }
37
+ danger(): this { return this.alertType('danger') }
25
38
 
26
39
  /**
27
40
  * Action buttons rendered as a footer row below the alert body —
@@ -36,14 +49,83 @@ export class Alert extends Element {
36
49
  return this
37
50
  }
38
51
 
52
+ /** Filament v5 parity alias for `actions([...])`. Identical semantics. */
53
+ controls(actions: Action[]): this {
54
+ return this.actions(actions)
55
+ }
56
+
57
+ /**
58
+ * Filament v5 parity — variadic `controlActions(a, b, c, …)` matches
59
+ * the spread shape `controlActions(Action::make(...), Action::make(...))`.
60
+ */
61
+ controlActions(...actions: Action[]): this {
62
+ return this.actions(actions)
63
+ }
64
+
65
+ /**
66
+ * Toggle the close (`×`) button rendered in the alert's top-right
67
+ * corner. Off by default (matches today's behaviour). Dismissal is
68
+ * per-mount (component-local state) unless paired with
69
+ * `persistDismissal(key)`, which writes to `localStorage` so the
70
+ * alert stays hidden across reloads.
71
+ *
72
+ * @example
73
+ * Alert.make('Heads up — billing downgrades on Friday.')
74
+ * .warning()
75
+ * .dismissible()
76
+ * .persistDismissal('billing-downgrade-2026-q2')
77
+ */
78
+ dismissible(value: boolean = true): this {
79
+ this._dismissible = value
80
+ return this
81
+ }
82
+
83
+ /**
84
+ * Persist dismissal under a stable localStorage key. Auto-arms
85
+ * `dismissible(true)` so the close button shows up. The key is
86
+ * stored under `pilotiq.alert.<key>` to namespace from other
87
+ * pilotiq localStorage entries; users only see the leaf segment.
88
+ */
89
+ persistDismissal(key: string): this {
90
+ this._persistKey = key
91
+ this._dismissible = true
92
+ return this
93
+ }
94
+
95
+ /**
96
+ * Override the icon color independent of the alert type. By default
97
+ * the renderer picks an icon hue matching `alertType`
98
+ * (info/warning/success/danger); call this to force a different one
99
+ * — e.g. a `warning`-typed alert with a `'destructive'` icon when
100
+ * the message escalates partway through a flow.
101
+ */
102
+ iconColor(color: IconColor): this {
103
+ this._iconColor = color
104
+ return this
105
+ }
106
+
107
+ /**
108
+ * Align the footer actions row. Defaults to `'start'` (LTR-left).
109
+ * Use `'end'` for "primary action sits opposite the close button"
110
+ * layouts; `'center'` for short single-button alerts.
111
+ */
112
+ footerActionsAlignment(alignment: AlertActionsAlignment): this {
113
+ this._actionsAlignment = alignment
114
+ return this
115
+ }
116
+
39
117
  getType(): string { return 'alert' }
40
118
 
41
119
  toMeta() {
42
120
  return {
43
- type: 'alert' as const,
44
- content: this.content,
121
+ type: 'alert' as const,
122
+ content: this.content,
45
123
  alertType: this._alertType,
46
- ...(this._title ? { title: this._title } : {}),
124
+ ...(this._title !== undefined ? { title: this._title } : {}),
125
+ ...(this._dismissible ? { dismissible: true } : {}),
126
+ ...(this._persistKey !== undefined ? { persistDismissal: this._persistKey } : {}),
127
+ ...(this._iconColor !== undefined ? { iconColor: this._iconColor } : {}),
128
+ ...(this._actionsAlignment !== 'start' ? { actionsAlignment: this._actionsAlignment } : {}),
47
129
  }
48
130
  }
49
131
  }
@@ -22,6 +22,7 @@ import {
22
22
  type RepeatableEntryRowMeta,
23
23
  } from '../entries/RepeatableEntry.js'
24
24
  import { Section } from './Section.js'
25
+ import { TextField } from '../fields/TextField.js'
25
26
 
26
27
  export interface SchemaContext {
27
28
  user?: { name?: string; email?: string; [key: string]: unknown }
@@ -321,6 +322,37 @@ async function resolveOne(el: Element, ctx: RenderContext): Promise<ElementMeta
321
322
  }
322
323
  }
323
324
 
325
+ // Filament v5 — `Action.modalContentFooter([Element…])` resolves through
326
+ // the standard walker so any inner Actions evaluate `.visible() /
327
+ // .disabled()` the same way as anywhere else, and non-Action chrome
328
+ // (Alert / Text / Heading / …) flows through the same rendering path.
329
+ // Stamped under `meta.modalContentFooter` so the renderer can mount it
330
+ // between the form body and the Cancel/Submit footer.
331
+ if (el instanceof Action) {
332
+ const footer = el.getModalContentFooter()
333
+ if (footer && footer.length > 0) {
334
+ meta['modalContentFooter'] = await resolveAll(footer, ctx)
335
+ }
336
+ }
337
+
338
+ // `TextField.prefixAction(Action) / suffixAction(Action)` — resolve the
339
+ // bound Actions through `resolveAll` so visibility / disabled rules
340
+ // evaluate the same way as anywhere else. Hidden Actions are dropped
341
+ // from the slot (returning a sparse single-element array → undefined
342
+ // collapses cleanly).
343
+ if (el instanceof TextField) {
344
+ const pre = el.getPrefixAction()
345
+ const suf = el.getSuffixAction()
346
+ if (pre) {
347
+ const [resolved] = await resolveAll([pre], ctx)
348
+ if (resolved) meta['prefixAction'] = resolved
349
+ }
350
+ if (suf) {
351
+ const [resolved] = await resolveAll([suf], ctx)
352
+ if (resolved) meta['suffixAction'] = resolved
353
+ }
354
+ }
355
+
324
356
  return meta
325
357
  }
326
358