@modufolio/panel 0.1.0 → 0.2.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 (73) hide show
  1. package/README.md +1 -1
  2. package/dist/Builder/dragHandle.d.ts +10 -0
  3. package/dist/Builder/schema.d.ts +1 -1
  4. package/dist/Components/Actions/Action.vue.d.ts +1 -1
  5. package/dist/Components/Columns/CellActions.vue.d.ts +7 -7
  6. package/dist/Components/Columns/SelectColumn.vue.d.ts +8 -2
  7. package/dist/Components/Core/Button.vue.d.ts +2 -2
  8. package/dist/Components/Core/FlashMessages.vue.d.ts +6 -1
  9. package/dist/Components/Core/SelectInput.vue.d.ts +1 -1
  10. package/dist/Components/Core/TextInput.vue.d.ts +1 -1
  11. package/dist/Components/Dialogs/Dialog.vue.d.ts +1 -1
  12. package/dist/Components/Drawer/Drawer.vue.d.ts +1 -1
  13. package/dist/Components/Drawer/DrawerLink.vue.d.ts +4 -3
  14. package/dist/Components/Drawer/DrawerRelationList.vue.d.ts +12 -10
  15. package/dist/Components/Drawer/DrawerStack.vue.d.ts +14 -14
  16. package/dist/Components/Drawer/useDrawerDirtyGuard.d.ts +17 -0
  17. package/dist/Components/Drawer/useDrawerStack.d.ts +1 -1
  18. package/dist/Components/Drawer/useIsDrawer.d.ts +8 -0
  19. package/dist/Components/Fields/BelongsToSelect.vue.d.ts +14 -9
  20. package/dist/Components/Fields/CheckboxField.vue.d.ts +2 -2
  21. package/dist/Components/Fields/ColorPickerField.vue.d.ts +3 -3
  22. package/dist/Components/Fields/DataField.vue.d.ts +55 -0
  23. package/dist/Components/Fields/DatePickerField.vue.d.ts +2 -2
  24. package/dist/Components/Fields/DateRangePickerField.vue.d.ts +2 -2
  25. package/dist/Components/Fields/DateTimePickerField.vue.d.ts +2 -2
  26. package/dist/Components/Fields/EmbedField.vue.d.ts +95 -0
  27. package/dist/Components/Fields/FieldDescription.vue.d.ts +25 -0
  28. package/dist/Components/Fields/FieldLabel.vue.d.ts +67 -0
  29. package/dist/Components/Fields/FieldMessage.vue.d.ts +25 -0
  30. package/dist/Components/Fields/FieldPrimitive.vue.d.ts +127 -0
  31. package/dist/Components/Fields/FileUploadField.vue.d.ts +2 -2
  32. package/dist/Components/Fields/HiddenField.vue.d.ts +28 -0
  33. package/dist/Components/Fields/MultiSelectField.vue.d.ts +3 -3
  34. package/dist/Components/Fields/ProseMirrorBuilderField.vue.d.ts +1 -1
  35. package/dist/Components/Fields/RangeField.vue.d.ts +2 -2
  36. package/dist/Components/Fields/RepeaterField.vue.d.ts +29 -15
  37. package/dist/Components/Fields/RichTextEditorField.vue.d.ts +3 -3
  38. package/dist/Components/Fields/SelectField.vue.d.ts +6 -5
  39. package/dist/Components/Fields/SetField.vue.d.ts +77 -0
  40. package/dist/Components/Fields/TagsField.vue.d.ts +3 -3
  41. package/dist/Components/Fields/TextField.vue.d.ts +4 -4
  42. package/dist/Components/Fields/TextareaField.vue.d.ts +3 -3
  43. package/dist/Components/Fields/TimePickerField.vue.d.ts +2 -2
  44. package/dist/Components/Fields/ToggleButtonsField.vue.d.ts +10 -5
  45. package/dist/Components/Fields/ToggleField.vue.d.ts +2 -2
  46. package/dist/Components/Fields/fieldsFromSpec.d.ts +10 -2
  47. package/dist/Components/Fields/useBlueprint.d.ts +4 -0
  48. package/dist/Components/Filters/DateRangeFilter.vue.d.ts +1 -1
  49. package/dist/Components/Filters/MultiSelectFilter.vue.d.ts +2 -2
  50. package/dist/Components/Filters/NumberFilter.vue.d.ts +1 -1
  51. package/dist/Components/Filters/SelectFilter.vue.d.ts +2 -2
  52. package/dist/Components/Filters/TernaryFilter.vue.d.ts +1 -1
  53. package/dist/Components/Layout/AppLayout.vue.d.ts +5 -3
  54. package/dist/Components/Layout/Breadcrumbs.vue.d.ts +2 -2
  55. package/dist/Components/Layout/Sidebar.vue.d.ts +22 -3
  56. package/dist/Components/Relations/RelationManager.vue.d.ts +4 -3
  57. package/dist/Components/Table/ExportButton.vue.d.ts +3 -3
  58. package/dist/Components/Table/SchemaCell.d.ts +7 -7
  59. package/dist/Components/Table/SchemaTable.vue.d.ts +21 -20
  60. package/dist/Components/Table/schemaLinks.d.ts +11 -3
  61. package/dist/Components/Table/tableSchema.d.ts +28 -11
  62. package/dist/Components/Table/tableTypes.d.ts +14 -1
  63. package/dist/Components/Table/useSchemaActions.d.ts +9 -26
  64. package/dist/Composables/useDeleteConfirmation.d.ts +11 -31
  65. package/dist/Composables/useNestedDrawerForm.d.ts +7 -0
  66. package/dist/index.css +1 -1
  67. package/dist/index.d.ts +6 -1
  68. package/dist/index.js +9951 -9770
  69. package/dist/index.js.map +1 -1
  70. package/docs/custom-fields.md +54 -2
  71. package/docs/drawer-protocol.md +27 -1
  72. package/docs/table-schema.md +5 -0
  73. package/package.json +2 -2
@@ -2,8 +2,9 @@
2
2
 
3
3
  Blueprint forms resolve field components through a registry. Built-ins cover
4
4
  the standard inputs (`text`, `textarea`, `select`, `multiselect`, `toggle`,
5
- `checkbox`, `date`, `date-range`, `file`, `color`, `belongs-to`, `repeater`,
6
- `toggle-buttons`). Anything app-specific is registered at boot:
5
+ `checkbox`, `range`, `date`, `datetime`, `time`, `date-range`, `file`, `color`,
6
+ `tags`, `belongs-to`, `repeater`, `toggle-buttons`, `set`, `embed`, `data`,
7
+ `hidden`). Anything app-specific is registered at boot:
7
8
 
8
9
  ```js
9
10
  createPanel({
@@ -51,6 +52,57 @@ A field component receives (via `useBlueprint`'s `fieldProps`):
51
52
  plus anything passed through the FieldDef's `props` object. Emit
52
53
  `update:modelValue` with the new value.
53
54
 
55
+ ### Render it inside `FieldPrimitive`
56
+
57
+ Do not hand-roll the label, the help text or the error message. `FieldPrimitive`
58
+ is the frame every built-in field renders inside — it owns the grid width, the
59
+ label, the description, the message, and the ARIA relationships between them —
60
+ and it hands the control what it needs through slot props:
61
+
62
+ ```vue
63
+ <template>
64
+ <FieldPrimitive
65
+ v-bind="{ width, id, label, help, error, required }"
66
+ wrapper-class="ui-field-signature"
67
+ v-slot="{ describedBy, invalid }"
68
+ >
69
+ <canvas :id="id" :aria-describedby="describedBy" :aria-invalid="invalid" />
70
+ </FieldPrimitive>
71
+ </template>
72
+
73
+ <script setup lang="ts">
74
+ import { FieldPrimitive, fieldWidthProp } from '@modufolio/panel'
75
+
76
+ const props = defineProps({ ...fieldWidthProp, /* … */ })
77
+ </script>
78
+ ```
79
+
80
+ | Slot prop | Use |
81
+ |---|---|
82
+ | `describedBy` | `aria-describedby` — the help and error ids, or `undefined` |
83
+ | `invalid` | `aria-invalid` — `true` while there is an error, else `undefined` |
84
+ | `descriptionId` / `errorId` | The individual ids, when the control wires them itself |
85
+
86
+ Pass the same `id` to the frame and to the control: the help and error ids
87
+ derive from it, and that is what connects the three.
88
+
89
+ A field wrapping **several** controls passes `as="fieldset"`, which renders the
90
+ caption as a `<legend>` — `<label for>` may only point at one control, so a
91
+ group's label would otherwise label nothing.
92
+
93
+ A layout the stacked frame cannot express — a checkbox whose label sits beside
94
+ the box — composes the parts instead:
95
+
96
+ ```vue
97
+ import { FieldLabel, FieldDescription, FieldMessage } from '@modufolio/panel'
98
+ ```
99
+
100
+ That split is what the built-ins do, and it exists because twenty-two of them
101
+ used to render this scaffolding themselves: three different spacings for the
102
+ gap under a label, `role="alert"` on some error paragraphs and not others, and
103
+ `aria-describedby` missing from most of them, so their help text was visible to
104
+ sighted users only.
105
+
54
106
  ### Container fields
55
107
 
56
108
  A field holding a list of rows (a repeater, a matrix) also receives:
@@ -71,7 +71,7 @@ stack's shared overlay stands down when no item in the stack is a drawer.
71
71
  **Frames are pointers, which is the point.** A row action can carry a dialog
72
72
  URL (`RowAction::dialog()`) instead of naming a behaviour the table has to
73
73
  implement, so a new interaction is a new route rather than a new case in the
74
- client. See [table-schema.md](../../../docs/table-schema.md#actions).
74
+ client. See [table-schema.md](../../docs/table-schema.md#actions).
75
75
 
76
76
  ## Client components
77
77
 
@@ -88,6 +88,32 @@ client. See [table-schema.md](../../../docs/table-schema.md#actions).
88
88
  given a `stack` prop, so the highlighted row follows record pagination;
89
89
  reach for the composable directly only outside `SchemaTable`.
90
90
 
91
+ ## Unsaved changes
92
+
93
+ Closing a frame with edits in it must ask first, and there are five ways to
94
+ close one: the X, the back arrow, the backdrop, Escape, and clicking a frame
95
+ further down the pile. Each used to decide for itself, so a form was protected
96
+ on some paths and not others.
97
+
98
+ They now all route through **one** discard dialog, raised whenever any frame
99
+ the action would remove reports unsaved changes. A form opts in by reporting
100
+ its own dirtiness:
101
+
102
+ ```ts
103
+ import { useDrawerDirtyGuard } from '@modufolio/panel'
104
+
105
+ const isDirty = computed(() => form.isDirty)
106
+ useDrawerDirtyGuard(isDirty)
107
+ ```
108
+
109
+ Nothing is guarded by default — a frame that never calls this closes without a
110
+ prompt, which is right for a read-only drawer. `NestedDrawerForm` is a real
111
+ `<form>` (so Enter submits), and its composable exposes `getChangedData()` for
112
+ sending only the delta on edit.
113
+
114
+ Background frames scale down as they recede, so a stack reads as depth rather
115
+ than as overlapping panels.
116
+
91
117
  ## Never hand-write the visit
92
118
 
93
119
  The request side is three things at once — the header, `only: ['stack']`, and
@@ -319,6 +319,11 @@ operator from that field's type, and value(s). Each operator carries its
319
319
  arity (`0`, `1` or `2`), so the UI knows how many inputs to draw. Conditions
320
320
  are ANDed and sent as `constraints[]`.
321
321
 
322
+ The value input follows the constraint's `type`: a number spinner, a date
323
+ picker, a Yes/No select for a boolean (whose single `is` operator takes a
324
+ value, rather than the pair of valueless operators it used to have), and a text
325
+ box otherwise.
326
+
322
327
  The server must treat both the field and the operator as allowlists — the
323
328
  client is a convenience, not a guarantee.
324
329
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modufolio/panel",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Schema-driven admin panel components for Inertia.js + Vue 3 — tables, blueprint forms, filters, actions, drawers, widgets.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -30,7 +30,7 @@
30
30
  "prepublishOnly": "npm run build",
31
31
  "test": "vitest --run --config vitest.config.ts",
32
32
  "type-check": "vue-tsc --noEmit -p tsconfig.json",
33
- "lint": "eslint src"
33
+ "lint": "eslint src --max-warnings 0"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "@heroicons/vue": "^2.0.0",