@verbb/plugin-kit-vue 2.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.
- package/CHANGELOG.md +14 -0
- package/LICENSE.md +21 -0
- package/README.md +132 -0
- package/dist/app/PluginKitProvider.d.ts +92 -0
- package/dist/app/PluginKitProvider.d.ts.map +1 -0
- package/dist/app/PluginKitProvider.js +75 -0
- package/dist/app/PluginKitProvider.js.map +1 -0
- package/dist/app/configure.d.ts +29 -0
- package/dist/app/configure.d.ts.map +1 -0
- package/dist/app/configure.js +35 -0
- package/dist/app/configure.js.map +1 -0
- package/dist/app/index.d.ts +5 -0
- package/dist/app/index.d.ts.map +1 -0
- package/dist/app/index.js +5 -0
- package/dist/app/mountShadowApp.d.ts +6 -0
- package/dist/app/mountShadowApp.d.ts.map +1 -0
- package/dist/app/mountShadowApp.js +2 -0
- package/dist/components/Button.d.ts +208 -0
- package/dist/components/Button.d.ts.map +1 -0
- package/dist/components/Button.js +71 -0
- package/dist/components/Button.js.map +1 -0
- package/dist/components/ButtonGroup.d.ts +22 -0
- package/dist/components/ButtonGroup.d.ts.map +1 -0
- package/dist/components/ButtonGroup.js +19 -0
- package/dist/components/ButtonGroup.js.map +1 -0
- package/dist/components/Calendar.d.ts +9 -0
- package/dist/components/Calendar.d.ts.map +1 -0
- package/dist/components/Calendar.js +13 -0
- package/dist/components/Calendar.js.map +1 -0
- package/dist/components/Checkbox.d.ts +177 -0
- package/dist/components/Checkbox.d.ts.map +1 -0
- package/dist/components/Checkbox.js +69 -0
- package/dist/components/Checkbox.js.map +1 -0
- package/dist/components/CheckboxInput.d.ts +210 -0
- package/dist/components/CheckboxInput.d.ts.map +1 -0
- package/dist/components/CheckboxInput.js +109 -0
- package/dist/components/CheckboxInput.js.map +1 -0
- package/dist/components/CheckboxSelect.d.ts +9 -0
- package/dist/components/CheckboxSelect.d.ts.map +1 -0
- package/dist/components/CheckboxSelect.js +13 -0
- package/dist/components/CheckboxSelect.js.map +1 -0
- package/dist/components/CodeEditor.d.ts +9 -0
- package/dist/components/CodeEditor.d.ts.map +1 -0
- package/dist/components/CodeEditor.js +13 -0
- package/dist/components/CodeEditor.js.map +1 -0
- package/dist/components/ColorInput.d.ts +9 -0
- package/dist/components/ColorInput.d.ts.map +1 -0
- package/dist/components/ColorInput.js +13 -0
- package/dist/components/ColorInput.js.map +1 -0
- package/dist/components/Combobox.d.ts +9 -0
- package/dist/components/Combobox.d.ts.map +1 -0
- package/dist/components/Combobox.js +13 -0
- package/dist/components/Combobox.js.map +1 -0
- package/dist/components/ComboboxInput.d.ts +410 -0
- package/dist/components/ComboboxInput.d.ts.map +1 -0
- package/dist/components/ComboboxInput.js +174 -0
- package/dist/components/ComboboxInput.js.map +1 -0
- package/dist/components/CopyButton.d.ts +9 -0
- package/dist/components/CopyButton.d.ts.map +1 -0
- package/dist/components/CopyButton.js +13 -0
- package/dist/components/CopyButton.js.map +1 -0
- package/dist/components/DatePicker.d.ts +9 -0
- package/dist/components/DatePicker.d.ts.map +1 -0
- package/dist/components/DatePicker.js +13 -0
- package/dist/components/DatePicker.js.map +1 -0
- package/dist/components/Dialog.d.ts +9 -0
- package/dist/components/Dialog.d.ts.map +1 -0
- package/dist/components/Dialog.js +13 -0
- package/dist/components/Dialog.js.map +1 -0
- package/dist/components/DropdownMenu.d.ts +29 -0
- package/dist/components/DropdownMenu.d.ts.map +1 -0
- package/dist/components/DropdownMenu.js +22 -0
- package/dist/components/DropdownMenu.js.map +1 -0
- package/dist/components/EditableTable.d.ts +9 -0
- package/dist/components/EditableTable.d.ts.map +1 -0
- package/dist/components/EditableTable.js +13 -0
- package/dist/components/EditableTable.js.map +1 -0
- package/dist/components/Field.d.ts +9 -0
- package/dist/components/Field.d.ts.map +1 -0
- package/dist/components/Field.js +13 -0
- package/dist/components/Field.js.map +1 -0
- package/dist/components/Icon.d.ts +9 -0
- package/dist/components/Icon.d.ts.map +1 -0
- package/dist/components/Icon.js +13 -0
- package/dist/components/Icon.js.map +1 -0
- package/dist/components/Input.d.ts +9 -0
- package/dist/components/Input.d.ts.map +1 -0
- package/dist/components/Input.js +13 -0
- package/dist/components/Input.js.map +1 -0
- package/dist/components/InputGroup.d.ts +43 -0
- package/dist/components/InputGroup.d.ts.map +1 -0
- package/dist/components/InputGroup.js +28 -0
- package/dist/components/InputGroup.js.map +1 -0
- package/dist/components/Lightswitch.d.ts +197 -0
- package/dist/components/Lightswitch.d.ts.map +1 -0
- package/dist/components/Lightswitch.js +74 -0
- package/dist/components/Lightswitch.js.map +1 -0
- package/dist/components/Popover.d.ts +9 -0
- package/dist/components/Popover.d.ts.map +1 -0
- package/dist/components/Popover.js +13 -0
- package/dist/components/Popover.js.map +1 -0
- package/dist/components/Popup.d.ts +9 -0
- package/dist/components/Popup.d.ts.map +1 -0
- package/dist/components/Popup.js +13 -0
- package/dist/components/Popup.js.map +1 -0
- package/dist/components/RadioGroup.d.ts +15 -0
- package/dist/components/RadioGroup.d.ts.map +1 -0
- package/dist/components/RadioGroup.js +16 -0
- package/dist/components/RadioGroup.js.map +1 -0
- package/dist/components/RadioGroupInput.d.ts +202 -0
- package/dist/components/RadioGroupInput.d.ts.map +1 -0
- package/dist/components/RadioGroupInput.js +84 -0
- package/dist/components/RadioGroupInput.js.map +1 -0
- package/dist/components/ScrollArea.d.ts +9 -0
- package/dist/components/ScrollArea.d.ts.map +1 -0
- package/dist/components/ScrollArea.js +13 -0
- package/dist/components/ScrollArea.js.map +1 -0
- package/dist/components/Select.d.ts +22 -0
- package/dist/components/Select.d.ts.map +1 -0
- package/dist/components/Select.js +19 -0
- package/dist/components/Select.js.map +1 -0
- package/dist/components/SelectInput.d.ts +311 -0
- package/dist/components/SelectInput.d.ts.map +1 -0
- package/dist/components/SelectInput.js +127 -0
- package/dist/components/SelectInput.js.map +1 -0
- package/dist/components/Separator.d.ts +9 -0
- package/dist/components/Separator.d.ts.map +1 -0
- package/dist/components/Separator.js +13 -0
- package/dist/components/Separator.js.map +1 -0
- package/dist/components/Spinner.d.ts +94 -0
- package/dist/components/Spinner.d.ts.map +1 -0
- package/dist/components/Spinner.js +40 -0
- package/dist/components/Spinner.js.map +1 -0
- package/dist/components/Status.d.ts +9 -0
- package/dist/components/Status.d.ts.map +1 -0
- package/dist/components/Status.js +13 -0
- package/dist/components/Status.js.map +1 -0
- package/dist/components/Tabs.d.ts +29 -0
- package/dist/components/Tabs.d.ts.map +1 -0
- package/dist/components/Tabs.js +22 -0
- package/dist/components/Tabs.js.map +1 -0
- package/dist/components/Textarea.d.ts +9 -0
- package/dist/components/Textarea.d.ts.map +1 -0
- package/dist/components/Textarea.js +13 -0
- package/dist/components/Textarea.js.map +1 -0
- package/dist/components/TimePicker.d.ts +9 -0
- package/dist/components/TimePicker.d.ts.map +1 -0
- package/dist/components/TimePicker.js +13 -0
- package/dist/components/TimePicker.js.map +1 -0
- package/dist/components/Tiptap.d.ts +22 -0
- package/dist/components/Tiptap.d.ts.map +1 -0
- package/dist/components/Tiptap.js +21 -0
- package/dist/components/Tiptap.js.map +1 -0
- package/dist/components/Toggle.d.ts +9 -0
- package/dist/components/Toggle.d.ts.map +1 -0
- package/dist/components/Toggle.js +13 -0
- package/dist/components/Toggle.js.map +1 -0
- package/dist/components/ToggleGroup.d.ts +9 -0
- package/dist/components/ToggleGroup.d.ts.map +1 -0
- package/dist/components/ToggleGroup.js +13 -0
- package/dist/components/ToggleGroup.js.map +1 -0
- package/dist/components/Tooltip.d.ts +9 -0
- package/dist/components/Tooltip.d.ts.map +1 -0
- package/dist/components/Tooltip.js +13 -0
- package/dist/components/Tooltip.js.map +1 -0
- package/dist/components/index.d.ts +38 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +38 -0
- package/dist/createPkComponent.d.ts +17 -0
- package/dist/createPkComponent.d.ts.map +1 -0
- package/dist/createPkComponent.js +33 -0
- package/dist/createPkComponent.js.map +1 -0
- package/dist/fault/AppFaultBoundary.d.ts +17 -0
- package/dist/fault/AppFaultBoundary.d.ts.map +1 -0
- package/dist/fault/AppFaultBoundary.js +31 -0
- package/dist/fault/AppFaultBoundary.js.map +1 -0
- package/dist/fault/AppFaultProvider.d.ts +116 -0
- package/dist/fault/AppFaultProvider.d.ts.map +1 -0
- package/dist/fault/AppFaultProvider.js +214 -0
- package/dist/fault/AppFaultProvider.js.map +1 -0
- package/dist/fault/FaultFallback.d.ts +88 -0
- package/dist/fault/FaultFallback.d.ts.map +1 -0
- package/dist/fault/FaultFallback.js +91 -0
- package/dist/fault/FaultFallback.js.map +1 -0
- package/dist/fault/buildSupportBundle.d.ts +3 -0
- package/dist/fault/buildSupportBundle.d.ts.map +1 -0
- package/dist/fault/buildSupportBundle.js +22 -0
- package/dist/fault/buildSupportBundle.js.map +1 -0
- package/dist/fault/index.d.ts +8 -0
- package/dist/fault/index.d.ts.map +1 -0
- package/dist/fault/index.js +7 -0
- package/dist/fault/isIgnorableGlobalError.d.ts +3 -0
- package/dist/fault/isIgnorableGlobalError.d.ts.map +1 -0
- package/dist/fault/isIgnorableGlobalError.js +14 -0
- package/dist/fault/isIgnorableGlobalError.js.map +1 -0
- package/dist/fault/types.d.ts +18 -0
- package/dist/fault/types.d.ts.map +1 -0
- package/dist/fault/useUiWatchdog.d.ts +14 -0
- package/dist/fault/useUiWatchdog.d.ts.map +1 -0
- package/dist/fault/useUiWatchdog.js +37 -0
- package/dist/fault/useUiWatchdog.js.map +1 -0
- package/dist/forms/Field.d.ts +123 -0
- package/dist/forms/Field.d.ts.map +1 -0
- package/dist/forms/Field.js +77 -0
- package/dist/forms/Field.js.map +1 -0
- package/dist/forms/SchemaFormEngine.d.ts +50 -0
- package/dist/forms/SchemaFormEngine.d.ts.map +1 -0
- package/dist/forms/SchemaFormEngine.js +372 -0
- package/dist/forms/SchemaFormEngine.js.map +1 -0
- package/dist/forms/SchemaFormFieldNode.d.ts +41 -0
- package/dist/forms/SchemaFormFieldNode.d.ts.map +1 -0
- package/dist/forms/SchemaFormFieldNode.js +73 -0
- package/dist/forms/SchemaFormFieldNode.js.map +1 -0
- package/dist/forms/assertSchemaRegistry.d.ts +17 -0
- package/dist/forms/assertSchemaRegistry.d.ts.map +1 -0
- package/dist/forms/assertSchemaRegistry.js +68 -0
- package/dist/forms/assertSchemaRegistry.js.map +1 -0
- package/dist/forms/builtin-field-loaders.d.ts +11 -0
- package/dist/forms/builtin-field-loaders.d.ts.map +1 -0
- package/dist/forms/builtin-field-loaders.js +31 -0
- package/dist/forms/builtin-field-loaders.js.map +1 -0
- package/dist/forms/components/FieldWrap.d.ts +124 -0
- package/dist/forms/components/FieldWrap.d.ts.map +1 -0
- package/dist/forms/components/FieldWrap.js +99 -0
- package/dist/forms/components/FieldWrap.js.map +1 -0
- package/dist/forms/components/ModalTabs.d.ts +147 -0
- package/dist/forms/components/ModalTabs.d.ts.map +1 -0
- package/dist/forms/components/ModalTabs.js +135 -0
- package/dist/forms/components/ModalTabs.js.map +1 -0
- package/dist/forms/components/index.d.ts +3 -0
- package/dist/forms/components/index.d.ts.map +1 -0
- package/dist/forms/components/schemaErrors.d.ts +4 -0
- package/dist/forms/components/schemaErrors.d.ts.map +1 -0
- package/dist/forms/components/schemaErrors.js +34 -0
- package/dist/forms/components/schemaErrors.js.map +1 -0
- package/dist/forms/datetime.d.ts +11 -0
- package/dist/forms/datetime.d.ts.map +1 -0
- package/dist/forms/datetime.js +35 -0
- package/dist/forms/datetime.js.map +1 -0
- package/dist/forms/engine/context.d.ts +44 -0
- package/dist/forms/engine/context.d.ts.map +1 -0
- package/dist/forms/engine/context.js +15 -0
- package/dist/forms/engine/context.js.map +1 -0
- package/dist/forms/fields/CheckboxSelectField.d.ts +29 -0
- package/dist/forms/fields/CheckboxSelectField.d.ts.map +1 -0
- package/dist/forms/fields/CheckboxSelectField.js +44 -0
- package/dist/forms/fields/CheckboxSelectField.js.map +1 -0
- package/dist/forms/fields/CodeEditorField.d.ts +29 -0
- package/dist/forms/fields/CodeEditorField.d.ts.map +1 -0
- package/dist/forms/fields/CodeEditorField.js +46 -0
- package/dist/forms/fields/CodeEditorField.js.map +1 -0
- package/dist/forms/fields/ColorField.d.ts +29 -0
- package/dist/forms/fields/ColorField.d.ts.map +1 -0
- package/dist/forms/fields/ColorField.js +42 -0
- package/dist/forms/fields/ColorField.js.map +1 -0
- package/dist/forms/fields/ComboboxField.d.ts +29 -0
- package/dist/forms/fields/ComboboxField.d.ts.map +1 -0
- package/dist/forms/fields/ComboboxField.js +47 -0
- package/dist/forms/fields/ComboboxField.js.map +1 -0
- package/dist/forms/fields/DateTimeField.d.ts +29 -0
- package/dist/forms/fields/DateTimeField.d.ts.map +1 -0
- package/dist/forms/fields/DateTimeField.js +54 -0
- package/dist/forms/fields/DateTimeField.js.map +1 -0
- package/dist/forms/fields/GroupField.d.ts +27 -0
- package/dist/forms/fields/GroupField.d.ts.map +1 -0
- package/dist/forms/fields/GroupField.js +55 -0
- package/dist/forms/fields/GroupField.js.map +1 -0
- package/dist/forms/fields/LightswitchField.d.ts +29 -0
- package/dist/forms/fields/LightswitchField.d.ts.map +1 -0
- package/dist/forms/fields/LightswitchField.js +39 -0
- package/dist/forms/fields/LightswitchField.js.map +1 -0
- package/dist/forms/fields/NumberField.d.ts +29 -0
- package/dist/forms/fields/NumberField.d.ts.map +1 -0
- package/dist/forms/fields/NumberField.js +44 -0
- package/dist/forms/fields/NumberField.js.map +1 -0
- package/dist/forms/fields/RadioGroupField.d.ts +29 -0
- package/dist/forms/fields/RadioGroupField.d.ts.map +1 -0
- package/dist/forms/fields/RadioGroupField.js +55 -0
- package/dist/forms/fields/RadioGroupField.js.map +1 -0
- package/dist/forms/fields/SelectField.d.ts +29 -0
- package/dist/forms/fields/SelectField.d.ts.map +1 -0
- package/dist/forms/fields/SelectField.js +58 -0
- package/dist/forms/fields/SelectField.js.map +1 -0
- package/dist/forms/fields/TextField.d.ts +29 -0
- package/dist/forms/fields/TextField.d.ts.map +1 -0
- package/dist/forms/fields/TextField.js +43 -0
- package/dist/forms/fields/TextField.js.map +1 -0
- package/dist/forms/fields/TextareaField.d.ts +29 -0
- package/dist/forms/fields/TextareaField.d.ts.map +1 -0
- package/dist/forms/fields/TextareaField.js +44 -0
- package/dist/forms/fields/TextareaField.js.map +1 -0
- package/dist/forms/fields/options.d.ts +13 -0
- package/dist/forms/fields/options.d.ts.map +1 -0
- package/dist/forms/fields/options.js +29 -0
- package/dist/forms/fields/options.js.map +1 -0
- package/dist/forms/index.d.ts +13 -0
- package/dist/forms/index.d.ts.map +1 -0
- package/dist/forms/index.js +12 -0
- package/dist/forms/registry.d.ts +10 -0
- package/dist/forms/registry.d.ts.map +1 -0
- package/dist/forms/registry.js +45 -0
- package/dist/forms/registry.js.map +1 -0
- package/dist/forms/useEngineField.d.ts +11 -0
- package/dist/forms/useEngineField.d.ts.map +1 -0
- package/dist/forms/useEngineField.js +34 -0
- package/dist/forms/useEngineField.js.map +1 -0
- package/dist/forms/utils.d.ts +6 -0
- package/dist/forms/utils.d.ts.map +1 -0
- package/dist/forms/utils.js +20 -0
- package/dist/forms/utils.js.map +1 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/useTranslation.d.ts +4 -0
- package/dist/hooks/useTranslation.d.ts.map +1 -0
- package/dist/hooks/useTranslation.js +10 -0
- package/dist/hooks/useTranslation.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/utils/cn.d.ts +4 -0
- package/dist/utils/cn.d.ts.map +1 -0
- package/dist/utils/cn.js +11 -0
- package/dist/utils/cn.js.map +1 -0
- package/dist/utils/craftHostBridge.d.ts +17 -0
- package/dist/utils/craftHostBridge.d.ts.map +1 -0
- package/dist/utils/craftHostBridge.js +29 -0
- package/dist/utils/craftHostBridge.js.map +1 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/pk-change.d.ts +5 -0
- package/dist/utils/pk-change.d.ts.map +1 -0
- package/dist/utils/pk-change.js +13 -0
- package/dist/utils/pk-change.js.map +1 -0
- package/package.json +109 -0
- package/style.css +4 -0
- package/tailwind-preflight-scope.css +28 -0
- package/tailwind-theme.css +245 -0
- package/vite-dev.mjs +60 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { assignSlotNodes } from "@lit-labs/vue-utils/wrapper-utils.js";
|
|
2
|
+
import { defineComponent, h } from "vue";
|
|
3
|
+
//#region src/createPkComponent.ts
|
|
4
|
+
/**
|
|
5
|
+
* Minimal Vue facade over a registered `<pk-*>` custom element.
|
|
6
|
+
* Props and listeners pass through; default slot children are distributed with slot attributes.
|
|
7
|
+
*/
|
|
8
|
+
function createPkComponent(options) {
|
|
9
|
+
return defineComponent({
|
|
10
|
+
name: options.name,
|
|
11
|
+
inheritAttrs: false,
|
|
12
|
+
setup(_props, { attrs, slots }) {
|
|
13
|
+
return () => h(options.tagName, attrs, assignSlotNodes(slots));
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
/** Turn `pk-date-picker` → `PkDatePicker` for consistent facade names. */
|
|
18
|
+
function pkTagToComponentName(tagName) {
|
|
19
|
+
return `Pk${(tagName.startsWith("pk-") ? tagName.slice(3) : tagName).split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("")}`;
|
|
20
|
+
}
|
|
21
|
+
/** Batch-create pass-through facades for a tag → export name map. */
|
|
22
|
+
function createPkComponentFamily(family) {
|
|
23
|
+
const components = {};
|
|
24
|
+
for (const [exportName, tagName] of Object.entries(family)) components[exportName] = createPkComponent({
|
|
25
|
+
name: pkTagToComponentName(tagName),
|
|
26
|
+
tagName
|
|
27
|
+
});
|
|
28
|
+
return components;
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { createPkComponent, createPkComponentFamily };
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=createPkComponent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createPkComponent.js","names":[],"sources":["../src/createPkComponent.ts"],"sourcesContent":["import { assignSlotNodes, type Slots } from '@lit-labs/vue-utils/wrapper-utils.js';\nimport { defineComponent, h } from 'vue';\n\n/**\n * Minimal Vue facade over a registered `<pk-*>` custom element.\n * Props and listeners pass through; default slot children are distributed with slot attributes.\n */\nexport function createPkComponent(options: { name: string; tagName: string }) {\n return defineComponent({\n name: options.name,\n inheritAttrs: false,\n setup(_props, { attrs, slots }) {\n return () => h(\n options.tagName,\n attrs,\n assignSlotNodes(slots as Slots),\n );\n },\n });\n}\n\n/** Turn `pk-date-picker` → `PkDatePicker` for consistent facade names. */\nexport function pkTagToComponentName(tagName: string): string {\n const slug = tagName.startsWith('pk-') ? tagName.slice(3) : tagName;\n\n return `Pk${slug.split('-').map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join('')}`;\n}\n\n/** Batch-create pass-through facades for a tag → export name map. */\nexport function createPkComponentFamily(family: Record<string, string>) {\n const components: Record<string, ReturnType<typeof createPkComponent>> = {};\n\n for (const [exportName, tagName] of Object.entries(family)) {\n components[exportName] = createPkComponent({\n name: pkTagToComponentName(tagName),\n tagName,\n });\n }\n\n return components;\n}\n"],"mappings":";;;;;;;AAOA,SAAgB,kBAAkB,SAA4C;AAC1E,QAAO,gBAAgB;EACnB,MAAM,QAAQ;EACd,cAAc;EACd,MAAM,QAAQ,EAAE,OAAO,SAAS;AAC5B,gBAAa,EACT,QAAQ,SACR,OACA,gBAAgB,MAAe,CAClC;;EAER,CAAC;;;AAIN,SAAgB,qBAAqB,SAAyB;AAG1D,QAAO,MAFM,QAAQ,WAAW,MAAM,GAAG,QAAQ,MAAM,EAAE,GAAG,SAE3C,MAAM,IAAI,CAAC,KAAK,SAAS,KAAK,OAAO,EAAE,CAAC,aAAa,GAAG,KAAK,MAAM,EAAE,CAAC,CAAC,KAAK,GAAG;;;AAIpG,SAAgB,wBAAwB,QAAgC;CACpE,MAAM,aAAmE,EAAE;AAE3E,MAAK,MAAM,CAAC,YAAY,YAAY,OAAO,QAAQ,OAAO,CACtD,YAAW,cAAc,kBAAkB;EACvC,MAAM,qBAAqB,QAAQ;EACnC;EACH,CAAC;AAGN,QAAO"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { VNodeChild } from 'vue';
|
|
2
|
+
import { AppFaultRecord } from './types.js';
|
|
3
|
+
type FaultPayload = Omit<AppFaultRecord, 'timestamp' | 'count'>;
|
|
4
|
+
/**
|
|
5
|
+
* Catches Vue render/lifecycle errors in the builder subtree via `onErrorCaptured`.
|
|
6
|
+
* Emits `fault` then returns null so the parent provider can show {@link FaultFallback}.
|
|
7
|
+
*
|
|
8
|
+
* Listen with `onFault` in `h()` / templates — Vue maps that to the `fault` emit
|
|
9
|
+
* (do not declare an `onFault` prop; `on*` keys are event listeners in `h()`).
|
|
10
|
+
*/
|
|
11
|
+
export declare const AppFaultBoundary: import('vue').DefineComponent<{}, () => VNodeChild, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
12
|
+
fault: (_fault: FaultPayload) => true;
|
|
13
|
+
}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{
|
|
14
|
+
onFault?: ((_fault: FaultPayload) => any) | undefined;
|
|
15
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=AppFaultBoundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppFaultBoundary.d.ts","sourceRoot":"","sources":["../../src/fault/AppFaultBoundary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyC,KAAK,UAAU,EAAE,MAAM,KAAK,CAAC;AAE7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,KAAK,YAAY,GAAG,IAAI,CAAC,cAAc,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC;AAEhE;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,0CAuBV,UAAU;oBApBL,YAAY;;;iFAsBlC,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { defineComponent, onErrorCaptured, ref } from "vue";
|
|
2
|
+
//#region src/fault/AppFaultBoundary.ts
|
|
3
|
+
/**
|
|
4
|
+
* Catches Vue render/lifecycle errors in the builder subtree via `onErrorCaptured`.
|
|
5
|
+
* Emits `fault` then returns null so the parent provider can show {@link FaultFallback}.
|
|
6
|
+
*
|
|
7
|
+
* Listen with `onFault` in `h()` / templates — Vue maps that to the `fault` emit
|
|
8
|
+
* (do not declare an `onFault` prop; `on*` keys are event listeners in `h()`).
|
|
9
|
+
*/
|
|
10
|
+
var AppFaultBoundary = defineComponent({
|
|
11
|
+
name: "AppFaultBoundary",
|
|
12
|
+
emits: { fault: (_fault) => true },
|
|
13
|
+
setup(_props, { slots, emit }) {
|
|
14
|
+
const hasError = ref(false);
|
|
15
|
+
onErrorCaptured((error, _instance, info) => {
|
|
16
|
+
hasError.value = true;
|
|
17
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
18
|
+
emit("fault", {
|
|
19
|
+
kind: "vue",
|
|
20
|
+
message: err.message,
|
|
21
|
+
stack: info ? `${err.stack ?? ""}\n\n${info}` : err.stack
|
|
22
|
+
});
|
|
23
|
+
return false;
|
|
24
|
+
});
|
|
25
|
+
return () => hasError.value ? null : slots.default?.();
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
//#endregion
|
|
29
|
+
export { AppFaultBoundary };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=AppFaultBoundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppFaultBoundary.js","names":[],"sources":["../../src/fault/AppFaultBoundary.ts"],"sourcesContent":["import { defineComponent, onErrorCaptured, ref, type VNodeChild } from 'vue';\n\nimport type { AppFaultRecord } from './types.js';\n\ntype FaultPayload = Omit<AppFaultRecord, 'timestamp' | 'count'>;\n\n/**\n * Catches Vue render/lifecycle errors in the builder subtree via `onErrorCaptured`.\n * Emits `fault` then returns null so the parent provider can show {@link FaultFallback}.\n *\n * Listen with `onFault` in `h()` / templates — Vue maps that to the `fault` emit\n * (do not declare an `onFault` prop; `on*` keys are event listeners in `h()`).\n */\nexport const AppFaultBoundary = defineComponent({\n name: 'AppFaultBoundary',\n emits: {\n fault: (_fault: FaultPayload) => true,\n },\n setup(_props, { slots, emit }) {\n const hasError = ref(false);\n\n onErrorCaptured((error, _instance, info) => {\n hasError.value = true;\n\n const err = error instanceof Error ? error : new Error(String(error));\n // Append Vue's component info string the same way React appends componentStack.\n emit('fault', {\n kind: 'vue',\n message: err.message,\n stack: info ? `${err.stack ?? ''}\\n\\n${info}` : err.stack,\n });\n\n // Stop propagation — the provider owns fatal UI; avoid duplicate parent handlers.\n return false;\n });\n\n return (): VNodeChild => (hasError.value ? null : slots.default?.());\n },\n});\n"],"mappings":";;;;;;;;;AAaA,IAAa,mBAAmB,gBAAgB;CAC5C,MAAM;CACN,OAAO,EACH,QAAQ,WAAyB,MACpC;CACD,MAAM,QAAQ,EAAE,OAAO,QAAQ;EAC3B,MAAM,WAAW,IAAI,MAAM;AAE3B,mBAAiB,OAAO,WAAW,SAAS;AACxC,YAAS,QAAQ;GAEjB,MAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC;AAErE,QAAK,SAAS;IACV,MAAM;IACN,SAAS,IAAI;IACb,OAAO,OAAO,GAAG,IAAI,SAAS,GAAG,MAAM,SAAS,IAAI;IACvD,CAAC;AAGF,UAAO;IACT;AAEF,eAA0B,SAAS,QAAQ,OAAO,MAAM,WAAW;;CAE1E,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { PropType, VNodeChild } from 'vue';
|
|
2
|
+
import { AppFaultContext, AppFaultKind, AppFaultRecord } from './types.js';
|
|
3
|
+
type RecordFaultInput = {
|
|
4
|
+
kind: AppFaultKind;
|
|
5
|
+
message: string;
|
|
6
|
+
stack?: string;
|
|
7
|
+
tagName?: string;
|
|
8
|
+
fatal?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export type AppFaultProviderProps = AppFaultContext & {
|
|
11
|
+
/** When false, skip the main-thread watchdog (useful in tests). */
|
|
12
|
+
enableWatchdog?: boolean;
|
|
13
|
+
/** Labels for the fault UI — pass translated strings from the host app. */
|
|
14
|
+
labels?: {
|
|
15
|
+
fatalTitle?: string;
|
|
16
|
+
fatalMessage?: string;
|
|
17
|
+
stuckTitle?: string;
|
|
18
|
+
stuckMessage?: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export type AppFaultContextValue = {
|
|
22
|
+
faults: AppFaultRecord[];
|
|
23
|
+
hasFatalFault: boolean;
|
|
24
|
+
isStuck: boolean;
|
|
25
|
+
recordFault: (input: RecordFaultInput) => void;
|
|
26
|
+
resetUi: () => void;
|
|
27
|
+
reload: () => void;
|
|
28
|
+
clearFaults: () => void;
|
|
29
|
+
dismissStuck: () => void;
|
|
30
|
+
};
|
|
31
|
+
export declare const AppFaultProvider: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
|
|
32
|
+
meta: {
|
|
33
|
+
type: PropType<Record<string, unknown>>;
|
|
34
|
+
default: undefined;
|
|
35
|
+
};
|
|
36
|
+
onResetUi: {
|
|
37
|
+
type: PropType<() => void>;
|
|
38
|
+
default: undefined;
|
|
39
|
+
};
|
|
40
|
+
onReload: {
|
|
41
|
+
type: PropType<() => void>;
|
|
42
|
+
default: undefined;
|
|
43
|
+
};
|
|
44
|
+
enableWatchdog: {
|
|
45
|
+
type: BooleanConstructor;
|
|
46
|
+
default: boolean;
|
|
47
|
+
};
|
|
48
|
+
labels: {
|
|
49
|
+
type: PropType<AppFaultProviderProps["labels"]>;
|
|
50
|
+
default: undefined;
|
|
51
|
+
};
|
|
52
|
+
}>, () => VNodeChild, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
|
|
53
|
+
meta: {
|
|
54
|
+
type: PropType<Record<string, unknown>>;
|
|
55
|
+
default: undefined;
|
|
56
|
+
};
|
|
57
|
+
onResetUi: {
|
|
58
|
+
type: PropType<() => void>;
|
|
59
|
+
default: undefined;
|
|
60
|
+
};
|
|
61
|
+
onReload: {
|
|
62
|
+
type: PropType<() => void>;
|
|
63
|
+
default: undefined;
|
|
64
|
+
};
|
|
65
|
+
enableWatchdog: {
|
|
66
|
+
type: BooleanConstructor;
|
|
67
|
+
default: boolean;
|
|
68
|
+
};
|
|
69
|
+
labels: {
|
|
70
|
+
type: PropType<AppFaultProviderProps["labels"]>;
|
|
71
|
+
default: undefined;
|
|
72
|
+
};
|
|
73
|
+
}>> & Readonly<{}>, {
|
|
74
|
+
meta: Record<string, unknown>;
|
|
75
|
+
onReload: () => void;
|
|
76
|
+
onResetUi: () => void;
|
|
77
|
+
labels: {
|
|
78
|
+
fatalTitle?: string;
|
|
79
|
+
fatalMessage?: string;
|
|
80
|
+
stuckTitle?: string;
|
|
81
|
+
stuckMessage?: string;
|
|
82
|
+
} | undefined;
|
|
83
|
+
enableWatchdog: boolean;
|
|
84
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
85
|
+
export declare function useAppFault(): AppFaultContextValue;
|
|
86
|
+
/** Optional composable — returns null outside a provider (for chrome mounted in separate trees). */
|
|
87
|
+
export declare function useAppFaultOptional(): AppFaultContextValue | null;
|
|
88
|
+
export type ResetUiButtonProps = {
|
|
89
|
+
className?: string;
|
|
90
|
+
label?: string;
|
|
91
|
+
};
|
|
92
|
+
/** Always-reachable overlay recovery — mount in builder chrome, not inside dialogs. */
|
|
93
|
+
export declare const ResetUiButton: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
|
|
94
|
+
className: {
|
|
95
|
+
type: StringConstructor;
|
|
96
|
+
default: undefined;
|
|
97
|
+
};
|
|
98
|
+
label: {
|
|
99
|
+
type: StringConstructor;
|
|
100
|
+
default: string;
|
|
101
|
+
};
|
|
102
|
+
}>, () => VNodeChild, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
|
|
103
|
+
className: {
|
|
104
|
+
type: StringConstructor;
|
|
105
|
+
default: undefined;
|
|
106
|
+
};
|
|
107
|
+
label: {
|
|
108
|
+
type: StringConstructor;
|
|
109
|
+
default: string;
|
|
110
|
+
};
|
|
111
|
+
}>> & Readonly<{}>, {
|
|
112
|
+
label: string;
|
|
113
|
+
className: string;
|
|
114
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
115
|
+
export {};
|
|
116
|
+
//# sourceMappingURL=AppFaultProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppFaultProvider.d.ts","sourceRoot":"","sources":["../../src/fault/AppFaultProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAUH,KAAK,QAAQ,EACb,KAAK,UAAU,EAClB,MAAM,KAAK,CAAC;AAMb,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGhF,KAAK,gBAAgB,GAAG;IACpB,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,eAAe,GAAG;IAClD,mEAAmE;IACnE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,2EAA2E;IAC3E,MAAM,CAAC,EAAE;QACL,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;CACL,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAC/B,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC/C,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,IAAI,CAAC;CAC5B,CAAC;AAOF,eAAO,MAAM,gBAAgB;;cAGG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;;cAC1B,QAAQ,CAAC,MAAM,IAAI,CAAC;;;;cACrB,QAAQ,CAAC,MAAM,IAAI,CAAC;;;;;;;;cAG9B,QAAQ,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;;;UAqKlD,UAAU;;cA1KG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;;cAC1B,QAAQ,CAAC,MAAM,IAAI,CAAC;;;;cACrB,QAAQ,CAAC,MAAM,IAAI,CAAC;;;;;;;;cAG9B,QAAQ,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;;;;;oBAHhB,IAAI;qBADH,IAAI;;qBA3BrC,MAAM;uBACJ,MAAM;qBACR,MAAM;uBACJ,MAAM;;;4EA6O3B,CAAC;AAEH,wBAAgB,WAAW,IAAI,oBAAoB,CAQlD;AAED,oGAAoG;AACpG,wBAAgB,mBAAmB,IAAI,oBAAoB,GAAG,IAAI,CAEjE;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,uFAAuF;AACvF,eAAO,MAAM,aAAa;;;;;;;;;UASP,UAAU;;;;;;;;;;;;4EAiB3B,CAAC"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { AppFaultBoundary } from "./AppFaultBoundary.js";
|
|
2
|
+
import { FaultFallback } from "./FaultFallback.js";
|
|
3
|
+
import { isIgnorableGlobalError } from "./isIgnorableGlobalError.js";
|
|
4
|
+
import { useUiWatchdog } from "./useUiWatchdog.js";
|
|
5
|
+
import { computed, defineComponent, h, inject, onMounted, onUnmounted, provide, ref } from "vue";
|
|
6
|
+
import { recoverOverlays } from "@verbb/plugin-kit-web/plugin-kit";
|
|
7
|
+
//#region src/fault/AppFaultProvider.ts
|
|
8
|
+
var AppFaultKey = Symbol("pluginKitAppFault");
|
|
9
|
+
var faultKey = (input) => `${input.kind}:${input.tagName ?? ""}:${input.message.split("\n")[0]}`;
|
|
10
|
+
var AppFaultProvider = defineComponent({
|
|
11
|
+
name: "AppFaultProvider",
|
|
12
|
+
props: {
|
|
13
|
+
meta: {
|
|
14
|
+
type: Object,
|
|
15
|
+
default: void 0
|
|
16
|
+
},
|
|
17
|
+
onResetUi: {
|
|
18
|
+
type: Function,
|
|
19
|
+
default: void 0
|
|
20
|
+
},
|
|
21
|
+
onReload: {
|
|
22
|
+
type: Function,
|
|
23
|
+
default: void 0
|
|
24
|
+
},
|
|
25
|
+
enableWatchdog: {
|
|
26
|
+
type: Boolean,
|
|
27
|
+
default: true
|
|
28
|
+
},
|
|
29
|
+
labels: {
|
|
30
|
+
type: Object,
|
|
31
|
+
default: void 0
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
setup(props, { slots }) {
|
|
35
|
+
const faults = ref([]);
|
|
36
|
+
const hasFatalFault = ref(false);
|
|
37
|
+
const isStuck = ref(false);
|
|
38
|
+
const seen = /* @__PURE__ */ new Map();
|
|
39
|
+
const recordFault = (input) => {
|
|
40
|
+
const key = faultKey(input);
|
|
41
|
+
const count = (seen.get(key) ?? 0) + 1;
|
|
42
|
+
seen.set(key, count);
|
|
43
|
+
faults.value = [{
|
|
44
|
+
kind: input.kind,
|
|
45
|
+
message: input.message,
|
|
46
|
+
stack: input.stack,
|
|
47
|
+
tagName: input.tagName,
|
|
48
|
+
timestamp: Date.now(),
|
|
49
|
+
count
|
|
50
|
+
}, ...faults.value.filter((item) => faultKey(item) !== key)].slice(0, 8);
|
|
51
|
+
if (input.fatal !== false && (input.kind === "vue" || input.kind === "global")) hasFatalFault.value = true;
|
|
52
|
+
};
|
|
53
|
+
const resetUi = () => {
|
|
54
|
+
const { actions, diagnostic } = recoverOverlays();
|
|
55
|
+
console.info("[plugin-kit] overlay recovery:", actions.join(", "), diagnostic.report);
|
|
56
|
+
props.onResetUi?.();
|
|
57
|
+
isStuck.value = false;
|
|
58
|
+
hasFatalFault.value = false;
|
|
59
|
+
faults.value = [];
|
|
60
|
+
seen.clear();
|
|
61
|
+
};
|
|
62
|
+
const reload = () => {
|
|
63
|
+
if (props.onReload) {
|
|
64
|
+
props.onReload();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
window.location.reload();
|
|
68
|
+
};
|
|
69
|
+
const clearFaults = () => {
|
|
70
|
+
hasFatalFault.value = false;
|
|
71
|
+
faults.value = [];
|
|
72
|
+
seen.clear();
|
|
73
|
+
};
|
|
74
|
+
const dismissStuck = () => {
|
|
75
|
+
isStuck.value = false;
|
|
76
|
+
};
|
|
77
|
+
provide(AppFaultKey, {
|
|
78
|
+
get faults() {
|
|
79
|
+
return faults.value;
|
|
80
|
+
},
|
|
81
|
+
get hasFatalFault() {
|
|
82
|
+
return hasFatalFault.value;
|
|
83
|
+
},
|
|
84
|
+
get isStuck() {
|
|
85
|
+
return isStuck.value;
|
|
86
|
+
},
|
|
87
|
+
recordFault,
|
|
88
|
+
resetUi,
|
|
89
|
+
reload,
|
|
90
|
+
clearFaults,
|
|
91
|
+
dismissStuck
|
|
92
|
+
});
|
|
93
|
+
const onResetShortcut = (event) => {
|
|
94
|
+
if (!((event.ctrlKey || event.metaKey) && event.shiftKey && (event.key === "U" || event.key === "u"))) return;
|
|
95
|
+
event.preventDefault();
|
|
96
|
+
resetUi();
|
|
97
|
+
};
|
|
98
|
+
const onError = (event) => {
|
|
99
|
+
if (isIgnorableGlobalError(event.message, event.error)) return;
|
|
100
|
+
recordFault({
|
|
101
|
+
kind: "global",
|
|
102
|
+
message: event.message || event.error?.message || "Unknown error",
|
|
103
|
+
stack: event.error?.stack,
|
|
104
|
+
fatal: true
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
const onRejection = (event) => {
|
|
108
|
+
const reason = event.reason;
|
|
109
|
+
const message = reason?.message ?? String(event.reason);
|
|
110
|
+
if (isIgnorableGlobalError(message, reason)) return;
|
|
111
|
+
recordFault({
|
|
112
|
+
kind: "rejection",
|
|
113
|
+
message,
|
|
114
|
+
stack: reason?.stack,
|
|
115
|
+
fatal: false
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
const onPkError = (event) => {
|
|
119
|
+
const detail = event.detail;
|
|
120
|
+
recordFault({
|
|
121
|
+
kind: "pk-error",
|
|
122
|
+
tagName: detail?.tagName,
|
|
123
|
+
message: detail?.message ?? "Web component error",
|
|
124
|
+
stack: detail?.stack,
|
|
125
|
+
fatal: false
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
onMounted(() => {
|
|
129
|
+
window.addEventListener("keydown", onResetShortcut, true);
|
|
130
|
+
window.addEventListener("error", onError);
|
|
131
|
+
window.addEventListener("unhandledrejection", onRejection);
|
|
132
|
+
window.addEventListener("pk-error", onPkError);
|
|
133
|
+
});
|
|
134
|
+
onUnmounted(() => {
|
|
135
|
+
window.removeEventListener("keydown", onResetShortcut, true);
|
|
136
|
+
window.removeEventListener("error", onError);
|
|
137
|
+
window.removeEventListener("unhandledrejection", onRejection);
|
|
138
|
+
window.removeEventListener("pk-error", onPkError);
|
|
139
|
+
});
|
|
140
|
+
useUiWatchdog({
|
|
141
|
+
enabled: computed(() => props.enableWatchdog && !hasFatalFault.value),
|
|
142
|
+
onStall: () => {
|
|
143
|
+
isStuck.value = true;
|
|
144
|
+
recordFault({
|
|
145
|
+
kind: "watchdog",
|
|
146
|
+
message: "The builder stopped responding.",
|
|
147
|
+
fatal: false
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
return () => h(AppFaultBoundary, { onFault: (fault) => recordFault({
|
|
152
|
+
...fault,
|
|
153
|
+
fatal: true
|
|
154
|
+
}) }, { default: () => {
|
|
155
|
+
if (hasFatalFault.value) return h(FaultFallback, {
|
|
156
|
+
title: props.labels?.fatalTitle,
|
|
157
|
+
message: props.labels?.fatalMessage,
|
|
158
|
+
faults: faults.value,
|
|
159
|
+
meta: props.meta,
|
|
160
|
+
onReload: reload,
|
|
161
|
+
onResetUi: resetUi
|
|
162
|
+
});
|
|
163
|
+
return [isStuck.value ? h("div", { class: "mb-3" }, h(FaultFallback, {
|
|
164
|
+
compact: true,
|
|
165
|
+
title: props.labels?.stuckTitle ?? "Builder became unresponsive",
|
|
166
|
+
message: props.labels?.stuckMessage ?? "The page may still scroll but clicks might not work. Reset UI to close stuck overlays, or reload if the problem continues.",
|
|
167
|
+
faults: faults.value,
|
|
168
|
+
meta: props.meta,
|
|
169
|
+
onReload: reload,
|
|
170
|
+
onResetUi: resetUi,
|
|
171
|
+
onDismiss: dismissStuck
|
|
172
|
+
})) : null, slots.default?.()];
|
|
173
|
+
} });
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
function useAppFault() {
|
|
177
|
+
const ctx = inject(AppFaultKey, null);
|
|
178
|
+
if (!ctx) throw new Error("useAppFault must be used within AppFaultProvider");
|
|
179
|
+
return ctx;
|
|
180
|
+
}
|
|
181
|
+
/** Optional composable — returns null outside a provider (for chrome mounted in separate trees). */
|
|
182
|
+
function useAppFaultOptional() {
|
|
183
|
+
return inject(AppFaultKey, null);
|
|
184
|
+
}
|
|
185
|
+
/** Always-reachable overlay recovery — mount in builder chrome, not inside dialogs. */
|
|
186
|
+
var ResetUiButton = defineComponent({
|
|
187
|
+
name: "ResetUiButton",
|
|
188
|
+
props: {
|
|
189
|
+
className: {
|
|
190
|
+
type: String,
|
|
191
|
+
default: void 0
|
|
192
|
+
},
|
|
193
|
+
label: {
|
|
194
|
+
type: String,
|
|
195
|
+
default: "Reset UI"
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
setup(props) {
|
|
199
|
+
const fault = useAppFaultOptional();
|
|
200
|
+
return () => {
|
|
201
|
+
if (!fault) return null;
|
|
202
|
+
return h("button", {
|
|
203
|
+
type: "button",
|
|
204
|
+
class: props.className,
|
|
205
|
+
title: "Close stuck dialogs and overlays",
|
|
206
|
+
onClick: fault.resetUi
|
|
207
|
+
}, props.label);
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
//#endregion
|
|
212
|
+
export { AppFaultProvider, ResetUiButton, useAppFault, useAppFaultOptional };
|
|
213
|
+
|
|
214
|
+
//# sourceMappingURL=AppFaultProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppFaultProvider.js","names":[],"sources":["../../src/fault/AppFaultProvider.ts"],"sourcesContent":["import {\n computed,\n defineComponent,\n h,\n inject,\n onMounted,\n onUnmounted,\n provide,\n ref,\n type InjectionKey,\n type PropType,\n type VNodeChild,\n} from 'vue';\nimport { recoverOverlays } from '@verbb/plugin-kit-web/plugin-kit';\n\nimport { AppFaultBoundary } from './AppFaultBoundary.js';\nimport { FaultFallback } from './FaultFallback.js';\nimport { isIgnorableGlobalError } from './isIgnorableGlobalError.js';\nimport type { AppFaultContext, AppFaultKind, AppFaultRecord } from './types.js';\nimport { useUiWatchdog } from './useUiWatchdog.js';\n\ntype RecordFaultInput = {\n kind: AppFaultKind;\n message: string;\n stack?: string;\n tagName?: string;\n fatal?: boolean;\n};\n\nexport type AppFaultProviderProps = AppFaultContext & {\n /** When false, skip the main-thread watchdog (useful in tests). */\n enableWatchdog?: boolean;\n /** Labels for the fault UI — pass translated strings from the host app. */\n labels?: {\n fatalTitle?: string;\n fatalMessage?: string;\n stuckTitle?: string;\n stuckMessage?: string;\n };\n};\n\nexport type AppFaultContextValue = {\n faults: AppFaultRecord[];\n hasFatalFault: boolean;\n isStuck: boolean;\n recordFault: (input: RecordFaultInput) => void;\n resetUi: () => void;\n reload: () => void;\n clearFaults: () => void;\n dismissStuck: () => void;\n};\n\nconst AppFaultKey: InjectionKey<AppFaultContextValue> = Symbol('pluginKitAppFault');\n\nconst faultKey = (input: RecordFaultInput | AppFaultRecord): string =>\n `${input.kind}:${input.tagName ?? ''}:${input.message.split('\\n')[0]}`;\n\nexport const AppFaultProvider = defineComponent({\n name: 'AppFaultProvider',\n props: {\n meta: { type: Object as PropType<Record<string, unknown>>, default: undefined },\n onResetUi: { type: Function as PropType<() => void>, default: undefined },\n onReload: { type: Function as PropType<() => void>, default: undefined },\n enableWatchdog: { type: Boolean, default: true },\n labels: {\n type: Object as PropType<AppFaultProviderProps['labels']>,\n default: undefined,\n },\n },\n setup(props, { slots }) {\n const faults = ref<AppFaultRecord[]>([]);\n const hasFatalFault = ref(false);\n const isStuck = ref(false);\n const seen = new Map<string, number>();\n\n const recordFault = (input: RecordFaultInput) => {\n const key = faultKey(input);\n const count = (seen.get(key) ?? 0) + 1;\n seen.set(key, count);\n\n const record: AppFaultRecord = {\n kind: input.kind,\n message: input.message,\n stack: input.stack,\n tagName: input.tagName,\n timestamp: Date.now(),\n count,\n };\n\n // Dedupe by key, keep newest first, cap at 8 for support bundles.\n faults.value = [record, ...faults.value.filter((item) => faultKey(item) !== key)].slice(0, 8);\n\n if (input.fatal !== false && (input.kind === 'vue' || input.kind === 'global')) {\n hasFatalFault.value = true;\n }\n };\n\n const resetUi = () => {\n const { actions, diagnostic } = recoverOverlays();\n console.info('[plugin-kit] overlay recovery:', actions.join(', '), diagnostic.report);\n props.onResetUi?.();\n isStuck.value = false;\n hasFatalFault.value = false;\n faults.value = [];\n seen.clear();\n };\n\n const reload = () => {\n if (props.onReload) {\n props.onReload();\n return;\n }\n\n window.location.reload();\n };\n\n const clearFaults = () => {\n hasFatalFault.value = false;\n faults.value = [];\n seen.clear();\n };\n\n const dismissStuck = () => {\n isStuck.value = false;\n };\n\n // Provide a reactive snapshot — inject consumers read .value via computed unwrap in templates,\n // but composables get the live refs through this object (mutated in place below).\n const contextValue: AppFaultContextValue = {\n get faults() {\n return faults.value;\n },\n get hasFatalFault() {\n return hasFatalFault.value;\n },\n get isStuck() {\n return isStuck.value;\n },\n recordFault,\n resetUi,\n reload,\n clearFaults,\n dismissStuck,\n };\n\n provide(AppFaultKey, contextValue);\n\n const onResetShortcut = (event: KeyboardEvent) => {\n const combo =\n (event.ctrlKey || event.metaKey) &&\n event.shiftKey &&\n (event.key === 'U' || event.key === 'u');\n\n if (!combo) {\n return;\n }\n\n event.preventDefault();\n resetUi();\n };\n\n const onError = (event: ErrorEvent) => {\n if (isIgnorableGlobalError(event.message, event.error)) {\n return;\n }\n\n recordFault({\n kind: 'global',\n message: event.message || event.error?.message || 'Unknown error',\n stack: event.error?.stack,\n fatal: true,\n });\n };\n\n const onRejection = (event: PromiseRejectionEvent) => {\n const reason = event.reason as Error | undefined;\n const message = reason?.message ?? String(event.reason);\n\n if (isIgnorableGlobalError(message, reason)) {\n return;\n }\n\n recordFault({\n kind: 'rejection',\n message,\n stack: reason?.stack,\n fatal: false,\n });\n };\n\n const onPkError = (event: Event) => {\n const detail = (event as CustomEvent<{ tagName?: string; message?: string; stack?: string }>)\n .detail;\n\n recordFault({\n kind: 'pk-error',\n tagName: detail?.tagName,\n message: detail?.message ?? 'Web component error',\n stack: detail?.stack,\n fatal: false,\n });\n };\n\n onMounted(() => {\n window.addEventListener('keydown', onResetShortcut, true);\n window.addEventListener('error', onError);\n window.addEventListener('unhandledrejection', onRejection);\n window.addEventListener('pk-error', onPkError);\n });\n\n onUnmounted(() => {\n window.removeEventListener('keydown', onResetShortcut, true);\n window.removeEventListener('error', onError);\n window.removeEventListener('unhandledrejection', onRejection);\n window.removeEventListener('pk-error', onPkError);\n });\n\n // Pause the watchdog once a fatal screen is up — no point flagging \"stuck\" over it.\n useUiWatchdog({\n enabled: computed(() => props.enableWatchdog && !hasFatalFault.value),\n onStall: () => {\n isStuck.value = true;\n recordFault({\n kind: 'watchdog',\n message: 'The builder stopped responding.',\n fatal: false,\n });\n },\n });\n\n return (): VNodeChild =>\n h(AppFaultBoundary, {\n onFault: (fault: Omit<AppFaultRecord, 'timestamp' | 'count'>) =>\n recordFault({\n ...fault,\n fatal: true,\n }),\n }, {\n default: () => {\n if (hasFatalFault.value) {\n return h(FaultFallback, {\n title: props.labels?.fatalTitle,\n message: props.labels?.fatalMessage,\n faults: faults.value,\n meta: props.meta,\n onReload: reload,\n onResetUi: resetUi,\n });\n }\n\n return [\n isStuck.value\n ? h(\n 'div',\n { class: 'mb-3' },\n h(FaultFallback, {\n compact: true,\n title: props.labels?.stuckTitle ?? 'Builder became unresponsive',\n message:\n props.labels?.stuckMessage ??\n 'The page may still scroll but clicks might not work. Reset UI to close stuck overlays, or reload if the problem continues.',\n faults: faults.value,\n meta: props.meta,\n onReload: reload,\n onResetUi: resetUi,\n onDismiss: dismissStuck,\n }),\n )\n : null,\n slots.default?.(),\n ];\n },\n });\n },\n});\n\nexport function useAppFault(): AppFaultContextValue {\n const ctx = inject(AppFaultKey, null);\n\n if (!ctx) {\n throw new Error('useAppFault must be used within AppFaultProvider');\n }\n\n return ctx;\n}\n\n/** Optional composable — returns null outside a provider (for chrome mounted in separate trees). */\nexport function useAppFaultOptional(): AppFaultContextValue | null {\n return inject(AppFaultKey, null);\n}\n\nexport type ResetUiButtonProps = {\n className?: string;\n label?: string;\n};\n\n/** Always-reachable overlay recovery — mount in builder chrome, not inside dialogs. */\nexport const ResetUiButton = defineComponent({\n name: 'ResetUiButton',\n props: {\n className: { type: String, default: undefined },\n label: { type: String, default: 'Reset UI' },\n },\n setup(props) {\n const fault = useAppFaultOptional();\n\n return (): VNodeChild => {\n if (!fault) {\n return null;\n }\n\n return h(\n 'button',\n {\n type: 'button',\n class: props.className,\n title: 'Close stuck dialogs and overlays',\n onClick: fault.resetUi,\n },\n props.label,\n );\n };\n },\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { PropType, VNodeChild } from 'vue';
|
|
2
|
+
import { AppFaultRecord } from './types.js';
|
|
3
|
+
export type FaultFallbackProps = {
|
|
4
|
+
title?: string;
|
|
5
|
+
message?: string;
|
|
6
|
+
faults: AppFaultRecord[];
|
|
7
|
+
meta?: Record<string, unknown>;
|
|
8
|
+
onReload: () => void;
|
|
9
|
+
onResetUi?: () => void;
|
|
10
|
+
onDismiss?: () => void;
|
|
11
|
+
/** When true, show inline banner styling instead of full-panel takeover. */
|
|
12
|
+
compact?: boolean;
|
|
13
|
+
};
|
|
14
|
+
export declare const FaultFallback: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
|
|
15
|
+
title: {
|
|
16
|
+
type: StringConstructor;
|
|
17
|
+
default: string;
|
|
18
|
+
};
|
|
19
|
+
message: {
|
|
20
|
+
type: StringConstructor;
|
|
21
|
+
default: string;
|
|
22
|
+
};
|
|
23
|
+
faults: {
|
|
24
|
+
type: PropType<AppFaultRecord[]>;
|
|
25
|
+
required: true;
|
|
26
|
+
};
|
|
27
|
+
meta: {
|
|
28
|
+
type: PropType<Record<string, unknown>>;
|
|
29
|
+
default: undefined;
|
|
30
|
+
};
|
|
31
|
+
onReload: {
|
|
32
|
+
type: PropType<() => void>;
|
|
33
|
+
required: true;
|
|
34
|
+
};
|
|
35
|
+
onResetUi: {
|
|
36
|
+
type: PropType<() => void>;
|
|
37
|
+
default: undefined;
|
|
38
|
+
};
|
|
39
|
+
onDismiss: {
|
|
40
|
+
type: PropType<() => void>;
|
|
41
|
+
default: undefined;
|
|
42
|
+
};
|
|
43
|
+
compact: {
|
|
44
|
+
type: BooleanConstructor;
|
|
45
|
+
default: boolean;
|
|
46
|
+
};
|
|
47
|
+
}>, () => VNodeChild, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
|
|
48
|
+
title: {
|
|
49
|
+
type: StringConstructor;
|
|
50
|
+
default: string;
|
|
51
|
+
};
|
|
52
|
+
message: {
|
|
53
|
+
type: StringConstructor;
|
|
54
|
+
default: string;
|
|
55
|
+
};
|
|
56
|
+
faults: {
|
|
57
|
+
type: PropType<AppFaultRecord[]>;
|
|
58
|
+
required: true;
|
|
59
|
+
};
|
|
60
|
+
meta: {
|
|
61
|
+
type: PropType<Record<string, unknown>>;
|
|
62
|
+
default: undefined;
|
|
63
|
+
};
|
|
64
|
+
onReload: {
|
|
65
|
+
type: PropType<() => void>;
|
|
66
|
+
required: true;
|
|
67
|
+
};
|
|
68
|
+
onResetUi: {
|
|
69
|
+
type: PropType<() => void>;
|
|
70
|
+
default: undefined;
|
|
71
|
+
};
|
|
72
|
+
onDismiss: {
|
|
73
|
+
type: PropType<() => void>;
|
|
74
|
+
default: undefined;
|
|
75
|
+
};
|
|
76
|
+
compact: {
|
|
77
|
+
type: BooleanConstructor;
|
|
78
|
+
default: boolean;
|
|
79
|
+
};
|
|
80
|
+
}>> & Readonly<{}>, {
|
|
81
|
+
meta: Record<string, unknown>;
|
|
82
|
+
title: string;
|
|
83
|
+
message: string;
|
|
84
|
+
onResetUi: () => void;
|
|
85
|
+
onDismiss: () => void;
|
|
86
|
+
compact: boolean;
|
|
87
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
88
|
+
//# sourceMappingURL=FaultFallback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FaultFallback.d.ts","sourceRoot":"","sources":["../../src/fault/FaultFallback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE,MAAM,KAAK,CAAC;AAGzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,MAAM,kBAAkB,GAAG;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAQF,eAAO,MAAM,aAAa;;;;;;;;;;cAQO,QAAQ,CAAC,cAAc,EAAE,CAAC;;;;cAC3B,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;;cAC3B,QAAQ,CAAC,MAAM,IAAI,CAAC;;;;cACnB,QAAQ,CAAC,MAAM,IAAI,CAAC;;;;cACpB,QAAQ,CAAC,MAAM,IAAI,CAAC;;;;;;;UAcxC,UAAU;;;;;;;;;;cAlBI,QAAQ,CAAC,cAAc,EAAE,CAAC;;;;cAC3B,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;;cAC3B,QAAQ,CAAC,MAAM,IAAI,CAAC;;;;cACnB,QAAQ,CAAC,MAAM,IAAI,CAAC;;;;cACpB,QAAQ,CAAC,MAAM,IAAI,CAAC;;;;;;;;;;;qBADL,IAAI;qBACJ,IAAI;;4EAoExD,CAAC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { buildSupportBundle } from "./buildSupportBundle.js";
|
|
2
|
+
import { defineComponent, h } from "vue";
|
|
3
|
+
//#region src/fault/FaultFallback.ts
|
|
4
|
+
var btnClass = "inline-flex items-center justify-center rounded-md border border-black/10 bg-white px-3 py-1.5 text-sm font-medium text-gray-800 shadow-sm hover:bg-gray-50 disabled:opacity-50";
|
|
5
|
+
var btnPrimaryClass = "inline-flex items-center justify-center rounded-md border border-transparent bg-[#0d78f2] px-3 py-1.5 text-sm font-medium text-white shadow-sm hover:bg-[#0b6ad9] disabled:opacity-50";
|
|
6
|
+
var FaultFallback = defineComponent({
|
|
7
|
+
name: "FaultFallback",
|
|
8
|
+
props: {
|
|
9
|
+
title: {
|
|
10
|
+
type: String,
|
|
11
|
+
default: "Something went wrong"
|
|
12
|
+
},
|
|
13
|
+
message: {
|
|
14
|
+
type: String,
|
|
15
|
+
default: "The builder hit an unexpected error. You can try resetting the UI or reloading the builder."
|
|
16
|
+
},
|
|
17
|
+
faults: {
|
|
18
|
+
type: Array,
|
|
19
|
+
required: true
|
|
20
|
+
},
|
|
21
|
+
meta: {
|
|
22
|
+
type: Object,
|
|
23
|
+
default: void 0
|
|
24
|
+
},
|
|
25
|
+
onReload: {
|
|
26
|
+
type: Function,
|
|
27
|
+
required: true
|
|
28
|
+
},
|
|
29
|
+
onResetUi: {
|
|
30
|
+
type: Function,
|
|
31
|
+
default: void 0
|
|
32
|
+
},
|
|
33
|
+
onDismiss: {
|
|
34
|
+
type: Function,
|
|
35
|
+
default: void 0
|
|
36
|
+
},
|
|
37
|
+
compact: {
|
|
38
|
+
type: Boolean,
|
|
39
|
+
default: false
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
setup(props, { slots }) {
|
|
43
|
+
const copyDetails = async () => {
|
|
44
|
+
const text = buildSupportBundle(props.faults, props.meta);
|
|
45
|
+
try {
|
|
46
|
+
await navigator.clipboard.writeText(text);
|
|
47
|
+
} catch {
|
|
48
|
+
console.warn("[plugin-kit] support bundle:\n", text);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
return () => {
|
|
52
|
+
return h("div", {
|
|
53
|
+
class: props.compact ? "rounded-lg border border-amber-300 bg-amber-50 p-4 text-sm text-amber-950" : "rounded-lg border border-red-200 bg-red-50 p-6 text-sm text-red-900",
|
|
54
|
+
role: "alert"
|
|
55
|
+
}, [
|
|
56
|
+
h("div", { class: "font-semibold" }, props.title),
|
|
57
|
+
h("p", { class: "mt-2 text-[13px] leading-relaxed opacity-90" }, props.message),
|
|
58
|
+
slots.default?.(),
|
|
59
|
+
h("div", { class: "mt-4 flex flex-wrap gap-2" }, [
|
|
60
|
+
props.onResetUi ? h("button", {
|
|
61
|
+
type: "button",
|
|
62
|
+
class: btnClass,
|
|
63
|
+
onClick: props.onResetUi
|
|
64
|
+
}, "Reset UI") : null,
|
|
65
|
+
h("button", {
|
|
66
|
+
type: "button",
|
|
67
|
+
class: btnPrimaryClass,
|
|
68
|
+
onClick: props.onReload
|
|
69
|
+
}, "Reload builder"),
|
|
70
|
+
h("button", {
|
|
71
|
+
type: "button",
|
|
72
|
+
class: btnClass,
|
|
73
|
+
onClick: () => {
|
|
74
|
+
copyDetails();
|
|
75
|
+
}
|
|
76
|
+
}, "Copy details for support"),
|
|
77
|
+
props.onDismiss ? h("button", {
|
|
78
|
+
type: "button",
|
|
79
|
+
class: btnClass,
|
|
80
|
+
onClick: props.onDismiss
|
|
81
|
+
}, "Dismiss") : null
|
|
82
|
+
]),
|
|
83
|
+
!props.compact && props.faults[0]?.message ? h("pre", { class: "mt-4 max-h-40 overflow-auto rounded border border-red-200/60 bg-white/70 p-3 text-xs text-red-800" }, props.faults[0].message) : null
|
|
84
|
+
]);
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
//#endregion
|
|
89
|
+
export { FaultFallback };
|
|
90
|
+
|
|
91
|
+
//# sourceMappingURL=FaultFallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FaultFallback.js","names":[],"sources":["../../src/fault/FaultFallback.ts"],"sourcesContent":["import { defineComponent, h, type PropType, type VNodeChild } from 'vue';\n\nimport { buildSupportBundle } from './buildSupportBundle.js';\nimport type { AppFaultRecord } from './types.js';\n\nexport type FaultFallbackProps = {\n title?: string;\n message?: string;\n faults: AppFaultRecord[];\n meta?: Record<string, unknown>;\n onReload: () => void;\n onResetUi?: () => void;\n onDismiss?: () => void;\n /** When true, show inline banner styling instead of full-panel takeover. */\n compact?: boolean;\n};\n\nconst btnClass =\n 'inline-flex items-center justify-center rounded-md border border-black/10 bg-white px-3 py-1.5 text-sm font-medium text-gray-800 shadow-sm hover:bg-gray-50 disabled:opacity-50';\n\nconst btnPrimaryClass =\n 'inline-flex items-center justify-center rounded-md border border-transparent bg-[#0d78f2] px-3 py-1.5 text-sm font-medium text-white shadow-sm hover:bg-[#0b6ad9] disabled:opacity-50';\n\nexport const FaultFallback = defineComponent({\n name: 'FaultFallback',\n props: {\n title: { type: String, default: 'Something went wrong' },\n message: {\n type: String,\n default: 'The builder hit an unexpected error. You can try resetting the UI or reloading the builder.',\n },\n faults: { type: Array as PropType<AppFaultRecord[]>, required: true },\n meta: { type: Object as PropType<Record<string, unknown>>, default: undefined },\n onReload: { type: Function as PropType<() => void>, required: true },\n onResetUi: { type: Function as PropType<() => void>, default: undefined },\n onDismiss: { type: Function as PropType<() => void>, default: undefined },\n compact: { type: Boolean, default: false },\n },\n setup(props, { slots }) {\n const copyDetails = async () => {\n const text = buildSupportBundle(props.faults, props.meta);\n\n try {\n await navigator.clipboard.writeText(text);\n } catch {\n console.warn('[plugin-kit] support bundle:\\n', text);\n }\n };\n\n return (): VNodeChild => {\n const shellClass = props.compact\n ? 'rounded-lg border border-amber-300 bg-amber-50 p-4 text-sm text-amber-950'\n : 'rounded-lg border border-red-200 bg-red-50 p-6 text-sm text-red-900';\n\n return h('div', { class: shellClass, role: 'alert' }, [\n h('div', { class: 'font-semibold' }, props.title),\n h('p', { class: 'mt-2 text-[13px] leading-relaxed opacity-90' }, props.message),\n slots.default?.(),\n h('div', { class: 'mt-4 flex flex-wrap gap-2' }, [\n props.onResetUi\n ? h(\n 'button',\n { type: 'button', class: btnClass, onClick: props.onResetUi },\n 'Reset UI',\n )\n : null,\n h(\n 'button',\n { type: 'button', class: btnPrimaryClass, onClick: props.onReload },\n 'Reload builder',\n ),\n h(\n 'button',\n {\n type: 'button',\n class: btnClass,\n onClick: () => {\n void copyDetails();\n },\n },\n 'Copy details for support',\n ),\n props.onDismiss\n ? h(\n 'button',\n { type: 'button', class: btnClass, onClick: props.onDismiss },\n 'Dismiss',\n )\n : null,\n ]),\n !props.compact && props.faults[0]?.message\n ? h(\n 'pre',\n {\n class:\n 'mt-4 max-h-40 overflow-auto rounded border border-red-200/60 bg-white/70 p-3 text-xs text-red-800',\n },\n props.faults[0].message,\n )\n : null,\n ]);\n };\n },\n});\n"],"mappings":";;;AAiBA,IAAM,WACF;AAEJ,IAAM,kBACF;AAEJ,IAAa,gBAAgB,gBAAgB;CACzC,MAAM;CACN,OAAO;EACH,OAAO;GAAE,MAAM;GAAQ,SAAS;GAAwB;EACxD,SAAS;GACL,MAAM;GACN,SAAS;GACZ;EACD,QAAQ;GAAE,MAAM;GAAqC,UAAU;GAAM;EACrE,MAAM;GAAE,MAAM;GAA6C,SAAS,KAAA;GAAW;EAC/E,UAAU;GAAE,MAAM;GAAkC,UAAU;GAAM;EACpE,WAAW;GAAE,MAAM;GAAkC,SAAS,KAAA;GAAW;EACzE,WAAW;GAAE,MAAM;GAAkC,SAAS,KAAA;GAAW;EACzE,SAAS;GAAE,MAAM;GAAS,SAAS;GAAO;EAC7C;CACD,MAAM,OAAO,EAAE,SAAS;EACpB,MAAM,cAAc,YAAY;GAC5B,MAAM,OAAO,mBAAmB,MAAM,QAAQ,MAAM,KAAK;AAEzD,OAAI;AACA,UAAM,UAAU,UAAU,UAAU,KAAK;WACrC;AACJ,YAAQ,KAAK,kCAAkC,KAAK;;;AAI5D,eAAyB;AAKrB,UAAO,EAAE,OAAO;IAAE,OAJC,MAAM,UACnB,8EACA;IAE+B,MAAM;IAAS,EAAE;IAClD,EAAE,OAAO,EAAE,OAAO,iBAAiB,EAAE,MAAM,MAAM;IACjD,EAAE,KAAK,EAAE,OAAO,+CAA+C,EAAE,MAAM,QAAQ;IAC/E,MAAM,WAAW;IACjB,EAAE,OAAO,EAAE,OAAO,6BAA6B,EAAE;KAC7C,MAAM,YACA,EACI,UACA;MAAE,MAAM;MAAU,OAAO;MAAU,SAAS,MAAM;MAAW,EAC7D,WACH,GACD;KACN,EACI,UACA;MAAE,MAAM;MAAU,OAAO;MAAiB,SAAS,MAAM;MAAU,EACnE,iBACH;KACD,EACI,UACA;MACI,MAAM;MACN,OAAO;MACP,eAAe;AACN,oBAAa;;MAEzB,EACD,2BACH;KACD,MAAM,YACA,EACI,UACA;MAAE,MAAM;MAAU,OAAO;MAAU,SAAS,MAAM;MAAW,EAC7D,UACH,GACD;KACT,CAAC;IACF,CAAC,MAAM,WAAW,MAAM,OAAO,IAAI,UAC7B,EACI,OACA,EACI,OACI,qGACP,EACD,MAAM,OAAO,GAAG,QACnB,GACD;IACT,CAAC;;;CAGb,CAAC"}
|