mechanica 1.0.25 → 2.0.0-alpha.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/LICENSE +21 -0
- package/README.md +123 -0
- package/bin/mechanica.js +11 -0
- package/dist/chunks/ImagePickerDialog-DZyxrbfv.js +468 -0
- package/dist/chunks/page-assets-DnDUQegn.js +534 -0
- package/dist/chunks/preview-uxnrJ5vY.js +431 -0
- package/dist/cli.js +0 -0
- package/dist/editor.css +2671 -0
- package/dist/editor.js +4851 -6469
- package/dist/index.js +230 -0
- package/dist/plugin.js +916 -547
- package/dist/types/cli/args.d.ts +8 -0
- package/dist/types/cli/build.d.ts +10 -0
- package/dist/types/cli/cli.d.ts +2 -0
- package/dist/types/cli/export.d.ts +40 -0
- package/dist/types/cli/headless.d.ts +60 -0
- package/dist/types/cli/page-assets.d.ts +65 -0
- package/dist/types/cli/push.d.ts +10 -0
- package/dist/types/cli/shot.d.ts +36 -0
- package/dist/types/cli/thumbs.d.ts +35 -0
- package/dist/types/compiler/compile-block.d.ts +45 -0
- package/dist/types/core/content.d.ts +7 -0
- package/dist/types/core/create-mechanica.d.ts +25 -0
- package/dist/types/core/data-registry.d.ts +15 -0
- package/dist/types/core/define-block.d.ts +48 -0
- package/dist/types/core/define-data.d.ts +26 -0
- package/dist/types/core/define-mechanica-app.d.ts +31 -0
- package/dist/types/core/field-types.d.ts +34 -0
- package/dist/types/core/index.d.ts +17 -0
- package/dist/types/core/link.d.ts +32 -0
- package/dist/types/core/load-blocks.d.ts +20 -0
- package/dist/types/core/preview.d.ts +54 -0
- package/dist/types/core/query.d.ts +8 -0
- package/dist/types/core/render-blocks.d.ts +15 -0
- package/dist/types/core/router.d.ts +42 -0
- package/dist/types/core/state.d.ts +30 -0
- package/dist/types/core/use-fetch.d.ts +8 -0
- package/dist/types/core/use-page-data.d.ts +3 -0
- package/dist/types/core/use-pages.d.ts +33 -0
- package/dist/types/core/use-pagination.d.ts +32 -0
- package/dist/types/editor/editor.d.ts +1 -0
- package/dist/types/editor/fields/builtin.d.ts +2 -0
- package/dist/types/editor/fields/registry.d.ts +27 -0
- package/dist/types/editor/fields/richtext/config.d.ts +17 -0
- package/dist/types/editor/fields/richtext/keys.d.ts +10 -0
- package/dist/types/editor/fields/richtext/widgets.d.ts +43 -0
- package/dist/types/editor/lib/block-meta.d.ts +24 -0
- package/dist/types/editor/lib/block-preview.d.ts +23 -0
- package/dist/types/editor/lib/bridge.d.ts +38 -0
- package/dist/types/editor/lib/content-tree.d.ts +42 -0
- package/dist/types/editor/lib/context-menu.d.ts +28 -0
- package/dist/types/editor/lib/drag-controller.d.ts +58 -0
- package/dist/types/editor/lib/history.d.ts +20 -0
- package/dist/types/editor/lib/navigation.d.ts +16 -0
- package/dist/types/editor/lib/page-list.d.ts +30 -0
- package/dist/types/editor/lib/panel-dock.d.ts +38 -0
- package/dist/types/editor/lib/recents.d.ts +8 -0
- package/dist/types/editor/lib/save-queue.d.ts +56 -0
- package/dist/types/editor/lib/shortcuts.d.ts +17 -0
- package/dist/types/editor/lib/store.d.ts +64 -0
- package/dist/types/editor/lib/tree-ui.d.ts +11 -0
- package/dist/types/editor/lib/types.d.ts +22 -0
- package/dist/types/editor/lib/use-block-frames.d.ts +62 -0
- package/dist/types/editor/props-panel/humanize.d.ts +2 -0
- package/dist/types/editor/props-panel/use-reorder.d.ts +22 -0
- package/dist/types/editor/ui/dialog.d.ts +23 -0
- package/dist/types/editor/widget-api.d.ts +35 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/svg-plugin.d.ts +2 -0
- package/dist/types/vite/collect-blocks.d.ts +28 -0
- package/dist/types/vite/collect-widgets.d.ts +12 -0
- package/dist/types/vite/dev/assets-store.d.ts +13 -0
- package/dist/types/vite/dev/data-store.d.ts +15 -0
- package/dist/types/vite/dev/fs-utils.d.ts +6 -0
- package/dist/types/vite/dev/middleware.d.ts +19 -0
- package/dist/types/vite/dev/page-state.d.ts +24 -0
- package/dist/types/vite/dev/pages-store.d.ts +89 -0
- package/dist/types/vite/dev/preview.d.ts +16 -0
- package/dist/types/vite/dev/query-dev.d.ts +13 -0
- package/dist/types/vite/entries.d.ts +43 -0
- package/dist/types/vite/index.d.ts +5 -0
- package/dist/types/vite/plugin.d.ts +37 -0
- package/dist/types/vite/rich-text-codec.d.ts +18 -0
- package/dist/widgets.js +35 -0
- package/package.json +67 -44
- package/src/cli/args.ts +33 -0
- package/src/cli/build.ts +41 -0
- package/src/cli/cli.ts +60 -0
- package/src/cli/export.ts +0 -0
- package/src/cli/headless.ts +361 -0
- package/src/cli/page-assets.ts +114 -0
- package/src/cli/push.ts +64 -0
- package/src/cli/shot.ts +237 -0
- package/src/cli/thumbs.ts +244 -0
- package/src/compiler/compile-block.ts +212 -0
- package/src/core/content.ts +24 -0
- package/src/core/create-mechanica.ts +107 -0
- package/src/core/data-registry.ts +34 -0
- package/src/core/define-block.ts +51 -0
- package/src/core/define-data.ts +59 -0
- package/src/core/define-mechanica-app.ts +54 -0
- package/src/core/field-types.ts +22 -0
- package/src/core/index.ts +48 -0
- package/src/core/link.ts +70 -0
- package/src/core/load-blocks.ts +38 -0
- package/src/core/preview.ts +221 -0
- package/src/core/query.ts +39 -0
- package/src/core/render-blocks.ts +42 -0
- package/src/core/router.ts +137 -0
- package/src/core/state.ts +35 -0
- package/src/core/use-fetch.ts +14 -0
- package/src/core/use-page-data.ts +10 -0
- package/src/core/use-pages.ts +39 -0
- package/src/core/use-pagination.ts +75 -0
- package/src/editor/EditorApp.vue +350 -0
- package/src/editor/components/BlockFrame.vue +18 -0
- package/src/editor/components/BlockPalette.vue +248 -0
- package/src/editor/components/BlockPreview.vue +127 -0
- package/src/editor/components/BlockSettings.vue +21 -0
- package/src/editor/components/DataSettings.vue +226 -0
- package/src/editor/components/HierarchyTree.vue +568 -0
- package/src/editor/components/PageBar.vue +109 -0
- package/src/editor/components/PanelToggle.vue +161 -0
- package/src/editor/components/VContextMenu.vue +179 -0
- package/src/editor/components/VIcon.vue +20 -0
- package/src/editor/components/VPopover.vue +129 -0
- package/src/editor/components/VSelect.vue +200 -0
- package/src/editor/dialogs/ConfirmDialog.vue +48 -0
- package/src/editor/dialogs/DataDialog.vue +16 -0
- package/src/editor/dialogs/ImagePickerDialog.vue +190 -0
- package/src/editor/dialogs/PagesDialog.vue +488 -0
- package/src/editor/dialogs/QuickSwitcher.vue +208 -0
- package/src/editor/dialogs/RichTextDialog.vue +38 -0
- package/src/editor/editor.ts +173 -0
- package/src/editor/fields/FieldControl.vue +31 -0
- package/src/editor/fields/builtin.ts +29 -0
- package/src/editor/fields/editors/BooleanField.vue +12 -0
- package/src/editor/fields/editors/ColorField.vue +12 -0
- package/src/editor/fields/editors/EnumField.vue +33 -0
- package/src/editor/fields/editors/ImageField.vue +132 -0
- package/src/editor/fields/editors/MultiselectField.vue +35 -0
- package/src/editor/fields/editors/NumberField.vue +12 -0
- package/src/editor/fields/editors/RichTextField.vue +59 -0
- package/src/editor/fields/editors/SmartLinkField.vue +457 -0
- package/src/editor/fields/editors/StringField.vue +15 -0
- package/src/editor/fields/editors/TextField.vue +15 -0
- package/src/editor/fields/registry.ts +52 -0
- package/src/editor/fields/richtext/RichCodeWidget.vue +120 -0
- package/src/editor/fields/richtext/RichImageWidget.vue +129 -0
- package/src/editor/fields/richtext/RichTableWidget.vue +54 -0
- package/src/editor/fields/richtext/RichTextEditor.vue +612 -0
- package/src/editor/fields/richtext/WidgetBoundary.vue +45 -0
- package/src/editor/fields/richtext/config.ts +77 -0
- package/src/editor/fields/richtext/keys.ts +12 -0
- package/src/editor/fields/richtext/widgets.ts +117 -0
- package/src/editor/icons/arrow-down.svg +1 -0
- package/src/editor/icons/arrow-up.svg +1 -0
- package/src/editor/icons/bold.svg +1 -0
- package/src/editor/icons/book.svg +1 -0
- package/src/editor/icons/check.svg +1 -0
- package/src/editor/icons/chevron-down.svg +1 -0
- package/src/editor/icons/close.svg +1 -0
- package/src/editor/icons/code.svg +1 -0
- package/src/editor/icons/copy.svg +1 -0
- package/src/editor/icons/ellipsis.svg +1 -0
- package/src/editor/icons/folder.svg +1 -0
- package/src/editor/icons/grip.svg +1 -0
- package/src/editor/icons/image.svg +1 -0
- package/src/editor/icons/info.svg +1 -0
- package/src/editor/icons/italic.svg +1 -0
- package/src/editor/icons/menu.svg +1 -0
- package/src/editor/icons/named-slots.svg +1 -0
- package/src/editor/icons/pencil.svg +1 -0
- package/src/editor/icons/plus.svg +1 -0
- package/src/editor/icons/redo.svg +1 -0
- package/src/editor/icons/search.svg +1 -0
- package/src/editor/icons/sliders.svg +1 -0
- package/src/editor/icons/slot.svg +1 -0
- package/src/editor/icons/strikethrough.svg +1 -0
- package/src/editor/icons/table.svg +4 -0
- package/src/editor/icons/trash.svg +1 -0
- package/src/editor/icons/underline.svg +1 -0
- package/src/editor/icons/undo.svg +1 -0
- package/src/editor/icons/upload.svg +1 -0
- package/src/editor/lib/block-meta.ts +72 -0
- package/src/editor/lib/block-preview.ts +78 -0
- package/src/editor/lib/bridge.ts +90 -0
- package/src/editor/lib/content-tree.ts +186 -0
- package/src/editor/lib/context-menu.ts +50 -0
- package/src/editor/lib/drag-controller.ts +217 -0
- package/src/editor/lib/history.ts +91 -0
- package/src/editor/lib/navigation.ts +31 -0
- package/src/editor/lib/page-list.ts +62 -0
- package/src/editor/lib/panel-dock.ts +97 -0
- package/src/editor/lib/recents.ts +31 -0
- package/src/editor/lib/save-queue.ts +156 -0
- package/src/editor/lib/shortcuts.ts +49 -0
- package/src/editor/lib/store.ts +295 -0
- package/src/editor/lib/tree-ui.ts +33 -0
- package/src/editor/lib/types.ts +24 -0
- package/src/editor/lib/use-block-frames.ts +125 -0
- package/src/editor/props-panel/ArrayField.vue +106 -0
- package/src/editor/props-panel/SchemaField.vue +45 -0
- package/src/editor/props-panel/SchemaForm.vue +21 -0
- package/src/editor/props-panel/VCollapse.vue +28 -0
- package/src/editor/props-panel/humanize.ts +8 -0
- package/src/editor/props-panel/use-reorder.ts +90 -0
- package/src/editor/styles/_variables.scss +54 -0
- package/src/editor/styles/editor.scss +915 -0
- package/src/editor/ui/VDialog.vue +95 -0
- package/src/editor/ui/VDialogHost.vue +108 -0
- package/src/editor/ui/dialog.ts +47 -0
- package/src/editor/widget-api.ts +46 -0
- package/src/index.ts +1 -0
- package/src/svg-plugin.ts +108 -0
- package/src/virtual-modules.d.ts +18 -0
- package/src/vite/collect-blocks.ts +99 -0
- package/src/vite/collect-widgets.ts +54 -0
- package/src/vite/dev/assets-store.ts +45 -0
- package/src/vite/dev/data-store.ts +61 -0
- package/src/vite/dev/fs-utils.ts +41 -0
- package/src/vite/dev/middleware.ts +197 -0
- package/src/vite/dev/page-state.ts +60 -0
- package/src/vite/dev/pages-store.ts +290 -0
- package/src/vite/dev/preview.ts +69 -0
- package/src/vite/dev/query-dev.ts +27 -0
- package/src/vite/entries.ts +124 -0
- package/src/vite/index.ts +16 -0
- package/src/vite/plugin.ts +442 -0
- package/src/vite/rich-text-codec.ts +48 -0
- package/src/vue-shim.d.ts +14 -0
- package/bin/bin.js +0 -37
- package/bin/build.js +0 -63
- package/bin/compile.js +0 -478
- package/bin/push.js +0 -80
- package/dist/editor.d.ts +0 -1
- package/dist/editor.js.map +0 -1
- package/dist/main.d.ts +0 -214
- package/dist/main.js +0 -314
- package/dist/main.js.map +0 -1
- package/dist/plugin.d.ts +0 -11
- package/dist/plugin.js.map +0 -1
- package/dist/schemaAliases-t4X-kaIk.js +0 -59
- package/dist/schemaAliases-t4X-kaIk.js.map +0 -1
- package/dist/style.css +0 -1448
- package/dist/updater.d.ts +0 -1
- package/dist/updater.js +0 -26
- package/dist/updater.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 den59k
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# mechanica
|
|
2
|
+
|
|
3
|
+
Build Vue 3 websites with a visual block editor. Authors write Vue SFC **blocks**, a visual editor arranges them into pages, and the result renders server-side and ships statically or via a backend.
|
|
4
|
+
|
|
5
|
+
Built for **Vite 8 / Vue 3.5 / Bun**.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
Works with plain Node ≥ 20.19 (npm/pnpm/yarn) or [Bun](https://bun.sh) — Bun installs run the TypeScript source directly, Node uses the compiled build. The fastest start is the scaffolder:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm create mechanica-app@latest my-site
|
|
13
|
+
# or: bun create mechanica-app my-site
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Or add it to an existing Vite + Vue project:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install mechanica
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick start
|
|
23
|
+
|
|
24
|
+
**`vite.config.ts`**
|
|
25
|
+
```ts
|
|
26
|
+
import { defineConfig } from 'vite'
|
|
27
|
+
import vue from '@vitejs/plugin-vue'
|
|
28
|
+
import { mechanica } from 'mechanica/plugin'
|
|
29
|
+
|
|
30
|
+
export default defineConfig({
|
|
31
|
+
plugins: [mechanica(), vue()],
|
|
32
|
+
})
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**`index.html`** — just a mount point; the plugin injects the entry and editor:
|
|
36
|
+
```html
|
|
37
|
+
<body><div id="app"></div></body>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**`src/main.ts`** — export an app definition (no `createApp`/`mount` yourself):
|
|
41
|
+
```ts
|
|
42
|
+
import { defineMechanicaApp } from 'mechanica'
|
|
43
|
+
import App from './App.vue'
|
|
44
|
+
|
|
45
|
+
export default defineMechanicaApp({ root: App })
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**`src/App.vue`** — render the page content somewhere:
|
|
49
|
+
```vue
|
|
50
|
+
<template>
|
|
51
|
+
<Content />
|
|
52
|
+
</template>
|
|
53
|
+
<script setup lang="ts">
|
|
54
|
+
import { Content } from 'mechanica'
|
|
55
|
+
</script>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**`src/blocks/Hero.vue`** — a block. `defineBlock` is a global macro (no import):
|
|
59
|
+
```vue
|
|
60
|
+
<template>
|
|
61
|
+
<section>
|
|
62
|
+
<h1>{{ props.title }}</h1>
|
|
63
|
+
<p>{{ props.subtitle }}</p>
|
|
64
|
+
</section>
|
|
65
|
+
</template>
|
|
66
|
+
<script setup lang="ts">
|
|
67
|
+
const props = defineBlock({
|
|
68
|
+
name: 'Hero',
|
|
69
|
+
category: 'Content',
|
|
70
|
+
props: {
|
|
71
|
+
title: { type: 'string', default: 'Hello' },
|
|
72
|
+
subtitle: 'text',
|
|
73
|
+
},
|
|
74
|
+
})
|
|
75
|
+
</script>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Run `vite` and open the page — the editor overlay lets you add Hero blocks and edit their props live.
|
|
79
|
+
|
|
80
|
+
## Authoring API
|
|
81
|
+
|
|
82
|
+
### `defineBlock(descriptor)` — the one macro
|
|
83
|
+
No import; used inside a block's `<script setup>`. Fields use [compact-json-schema](https://www.npmjs.com/package/compact-json-schema). Built-in field types: `string`, `text`, `number`, `boolean`, `color`, `image`, `file`, `smartLink`, `multiselect`, `richText`, plus `array`/`object`. Object-form fields take editor metadata (`label`, `description`, `default`, `placeholder`).
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
defineBlock({
|
|
87
|
+
name, category, icon, description, order, hidden,
|
|
88
|
+
props: { /* schema */ },
|
|
89
|
+
slots: ['default'], // auto-detected from <slot> if omitted
|
|
90
|
+
})
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### `defineData({ id, scope, props })` — shared data
|
|
94
|
+
An **imported function** (not a macro), used in a standalone module; returns a hook:
|
|
95
|
+
```ts
|
|
96
|
+
// data/header.ts
|
|
97
|
+
import { defineData } from 'mechanica'
|
|
98
|
+
export const useHeader = defineData({ id: 'header', scope: 'site', props: { logo: 'image' } })
|
|
99
|
+
// in a component: const header = useHeader()
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Components & composables
|
|
103
|
+
`<Content>`, `<Link :to="..." />` (string path or `smartLink` object), `useRouter`, `useRoute`, `usePages`, `useFetch`, `usePageData`.
|
|
104
|
+
|
|
105
|
+
### Custom field types
|
|
106
|
+
```ts
|
|
107
|
+
import { defineFieldType, registerFields } from 'mechanica/editor'
|
|
108
|
+
registerFields([
|
|
109
|
+
defineFieldType({ name: 'video', schema: { type: 'object', properties: { src: 'string' } }, editor: VideoField }),
|
|
110
|
+
])
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## CLI
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
mechanica build # client + SSR bundles → dist/
|
|
117
|
+
mechanica export # statically render every .mech page → export/
|
|
118
|
+
mechanica shot <blockId | /page/path> # headless screenshot of a block or page
|
|
119
|
+
mechanica thumbs [--blocks] # regenerate page / block thumbnails
|
|
120
|
+
mechanica push --key <apiKey> --host <url> # upload dist/ to a backend
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Page content lives in `.mech/pages/**.page.md` — a human-readable, Markdown-centric format equally editable by the visual editor, by hand, and by AI tools (rich text persists as plain Markdown).
|
package/bin/mechanica.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Under Bun, run the TS source directly (monorepo dev, Bun-native installs —
|
|
3
|
+
// always live, no build needed). Under Node, use the compiled CLI from dist/.
|
|
4
|
+
const entry = process.versions.bun ? '../src/cli/cli.ts' : '../dist/cli.js'
|
|
5
|
+
|
|
6
|
+
const { run } = await import(entry)
|
|
7
|
+
|
|
8
|
+
run(process.argv.slice(2)).catch((error) => {
|
|
9
|
+
console.error(error)
|
|
10
|
+
process.exit(1)
|
|
11
|
+
})
|
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
import { Fragment, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, inject, mergeProps, normalizeClass, onMounted, openBlock, ref, renderList, renderSlot, shallowReactive, toDisplayString, unref, withCtx, withModifiers } from "vue";
|
|
2
|
+
//#region \0svg-glob:C:\Users\Den\Desktop\CURVES\mechanica\packages\mechanica\src\editor\icons
|
|
3
|
+
var contents = {
|
|
4
|
+
"arrow-down": `<path d="M12 5v14"/><path d="m19 12-7 7-7-7"/>`,
|
|
5
|
+
"arrow-up": `<path d="M12 19V5"/><path d="m5 12 7-7 7 7"/>`,
|
|
6
|
+
"bold": `<path d="M6 4h7a4 4 0 0 1 0 8H6z"/><path d="M6 12h8a4 4 0 0 1 0 8H6z"/>`,
|
|
7
|
+
"book": `<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>`,
|
|
8
|
+
"check": `<polyline points="20 6 9 17 4 12"/>`,
|
|
9
|
+
"chevron-down": `<path d="m6 9 6 6 6-6"/>`,
|
|
10
|
+
"close": `<path d="M18 6 6 18"/><path d="m6 6 12 12"/>`,
|
|
11
|
+
"code": `<polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/>`,
|
|
12
|
+
"copy": `<rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>`,
|
|
13
|
+
"ellipsis": `<circle cx="5" cy="12" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="19" cy="12" r="2"/>`,
|
|
14
|
+
"folder": `<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>`,
|
|
15
|
+
"grip": `<circle cx="9" cy="5" r="1.6"/><circle cx="9" cy="12" r="1.6"/><circle cx="9" cy="19" r="1.6"/><circle cx="15" cy="5" r="1.6"/><circle cx="15" cy="12" r="1.6"/><circle cx="15" cy="19" r="1.6"/>`,
|
|
16
|
+
"image": `<rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>`,
|
|
17
|
+
"info": `<circle cx="12" cy="12" r="9"/><line x1="12" y1="11" x2="12" y2="16"/><line x1="12" y1="8" x2="12.01" y2="8"/>`,
|
|
18
|
+
"italic": `<line x1="19" y1="4" x2="10" y2="4"/><line x1="14" y1="20" x2="5" y2="20"/><line x1="15" y1="4" x2="9" y2="20"/>`,
|
|
19
|
+
"menu": `<path d="M3 6h18"/><path d="M3 12h18"/><path d="M3 18h18"/>`,
|
|
20
|
+
"named-slots": `<rect x="4" y="4" width="16" height="16" rx="2.5" stroke-dasharray="3.5 3"/><path d="M12 4.5v15"/>`,
|
|
21
|
+
"pencil": `<path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4Z"/>`,
|
|
22
|
+
"plus": `<path d="M12 5v14"/><path d="M5 12h14"/>`,
|
|
23
|
+
"redo": `<path d="M21 7v6h-6"/><path d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13"/>`,
|
|
24
|
+
"search": `<circle cx="11" cy="11" r="7"/><path d="m21 21-4.35-4.35"/>`,
|
|
25
|
+
"sliders": `<line x1="21" x2="14" y1="4" y2="4"/><line x1="10" x2="3" y1="4" y2="4"/><line x1="21" x2="12" y1="12" y2="12"/><line x1="8" x2="3" y1="12" y2="12"/><line x1="21" x2="16" y1="20" y2="20"/><line x1="12" x2="3" y1="20" y2="20"/><line x1="14" x2="14" y1="2" y2="6"/><line x1="8" x2="8" y1="10" y2="14"/><line x1="16" x2="16" y1="18" y2="22"/>`,
|
|
26
|
+
"slot": `<rect x="4" y="4" width="16" height="16" rx="2.5" stroke-dasharray="3.5 3"/>`,
|
|
27
|
+
"strikethrough": `<path d="M16 4H9a3 3 0 0 0-2.83 4"/><path d="M14 12a4 4 0 0 1 0 8H6"/><line x1="4" y1="12" x2="20" y2="12"/>`,
|
|
28
|
+
"table": `<rect x="3" y="4" width="18" height="16" rx="2" stroke="currentColor" stroke-width="2"/>
|
|
29
|
+
<path d="M3 9.5H21M9.5 9.5V20M15.5 9.5V20" stroke="currentColor" stroke-width="2"/>`,
|
|
30
|
+
"trash": `<path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><path d="M10 11v6"/><path d="M14 11v6"/>`,
|
|
31
|
+
"underline": `<path d="M6 4v6a6 6 0 0 0 12 0V4"/><line x1="4" y1="21" x2="20" y2="21"/>`,
|
|
32
|
+
"undo": `<path d="M3 7v6h6"/><path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"/>`,
|
|
33
|
+
"upload": `<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" x2="12" y1="3" y2="15"/>`
|
|
34
|
+
};
|
|
35
|
+
var attrs = {
|
|
36
|
+
"arrow-down": {
|
|
37
|
+
"viewBox": "0 0 24 24",
|
|
38
|
+
"fill": "none",
|
|
39
|
+
"stroke": "currentColor",
|
|
40
|
+
"stroke-width": "2",
|
|
41
|
+
"stroke-linecap": "round",
|
|
42
|
+
"stroke-linejoin": "round"
|
|
43
|
+
},
|
|
44
|
+
"arrow-up": {
|
|
45
|
+
"viewBox": "0 0 24 24",
|
|
46
|
+
"fill": "none",
|
|
47
|
+
"stroke": "currentColor",
|
|
48
|
+
"stroke-width": "2",
|
|
49
|
+
"stroke-linecap": "round",
|
|
50
|
+
"stroke-linejoin": "round"
|
|
51
|
+
},
|
|
52
|
+
"bold": {
|
|
53
|
+
"viewBox": "0 0 24 24",
|
|
54
|
+
"fill": "none",
|
|
55
|
+
"stroke": "currentColor",
|
|
56
|
+
"stroke-width": "2.25",
|
|
57
|
+
"stroke-linecap": "round",
|
|
58
|
+
"stroke-linejoin": "round"
|
|
59
|
+
},
|
|
60
|
+
"book": {
|
|
61
|
+
"viewBox": "0 0 24 24",
|
|
62
|
+
"fill": "none",
|
|
63
|
+
"stroke": "currentColor",
|
|
64
|
+
"stroke-width": "2",
|
|
65
|
+
"stroke-linecap": "round",
|
|
66
|
+
"stroke-linejoin": "round"
|
|
67
|
+
},
|
|
68
|
+
"check": {
|
|
69
|
+
"viewBox": "0 0 24 24",
|
|
70
|
+
"fill": "none",
|
|
71
|
+
"stroke": "currentColor",
|
|
72
|
+
"stroke-width": "2.5",
|
|
73
|
+
"stroke-linecap": "round",
|
|
74
|
+
"stroke-linejoin": "round"
|
|
75
|
+
},
|
|
76
|
+
"chevron-down": {
|
|
77
|
+
"viewBox": "0 0 24 24",
|
|
78
|
+
"fill": "none",
|
|
79
|
+
"stroke": "currentColor",
|
|
80
|
+
"stroke-width": "2",
|
|
81
|
+
"stroke-linecap": "round",
|
|
82
|
+
"stroke-linejoin": "round"
|
|
83
|
+
},
|
|
84
|
+
"close": {
|
|
85
|
+
"viewBox": "0 0 24 24",
|
|
86
|
+
"fill": "none",
|
|
87
|
+
"stroke": "currentColor",
|
|
88
|
+
"stroke-width": "2",
|
|
89
|
+
"stroke-linecap": "round",
|
|
90
|
+
"stroke-linejoin": "round"
|
|
91
|
+
},
|
|
92
|
+
"code": {
|
|
93
|
+
"viewBox": "0 0 24 24",
|
|
94
|
+
"fill": "none",
|
|
95
|
+
"stroke": "currentColor",
|
|
96
|
+
"stroke-width": "2",
|
|
97
|
+
"stroke-linecap": "round",
|
|
98
|
+
"stroke-linejoin": "round"
|
|
99
|
+
},
|
|
100
|
+
"copy": {
|
|
101
|
+
"viewBox": "0 0 24 24",
|
|
102
|
+
"fill": "none",
|
|
103
|
+
"stroke": "currentColor",
|
|
104
|
+
"stroke-width": "2",
|
|
105
|
+
"stroke-linecap": "round",
|
|
106
|
+
"stroke-linejoin": "round"
|
|
107
|
+
},
|
|
108
|
+
"ellipsis": {
|
|
109
|
+
"viewBox": "0 0 24 24",
|
|
110
|
+
"fill": "currentColor"
|
|
111
|
+
},
|
|
112
|
+
"folder": {
|
|
113
|
+
"viewBox": "0 0 24 24",
|
|
114
|
+
"fill": "none",
|
|
115
|
+
"stroke": "currentColor",
|
|
116
|
+
"stroke-width": "2",
|
|
117
|
+
"stroke-linecap": "round",
|
|
118
|
+
"stroke-linejoin": "round"
|
|
119
|
+
},
|
|
120
|
+
"grip": {
|
|
121
|
+
"viewBox": "0 0 24 24",
|
|
122
|
+
"fill": "currentColor",
|
|
123
|
+
"stroke": "none"
|
|
124
|
+
},
|
|
125
|
+
"image": {
|
|
126
|
+
"width": "24",
|
|
127
|
+
"height": "24",
|
|
128
|
+
"viewBox": "0 0 24 24",
|
|
129
|
+
"fill": "none",
|
|
130
|
+
"stroke": "currentColor",
|
|
131
|
+
"stroke-width": "2",
|
|
132
|
+
"stroke-linecap": "round",
|
|
133
|
+
"stroke-linejoin": "round"
|
|
134
|
+
},
|
|
135
|
+
"info": {
|
|
136
|
+
"viewBox": "0 0 24 24",
|
|
137
|
+
"fill": "none",
|
|
138
|
+
"stroke": "currentColor",
|
|
139
|
+
"stroke-width": "2",
|
|
140
|
+
"stroke-linecap": "round",
|
|
141
|
+
"stroke-linejoin": "round"
|
|
142
|
+
},
|
|
143
|
+
"italic": {
|
|
144
|
+
"viewBox": "0 0 24 24",
|
|
145
|
+
"fill": "none",
|
|
146
|
+
"stroke": "currentColor",
|
|
147
|
+
"stroke-width": "2",
|
|
148
|
+
"stroke-linecap": "round",
|
|
149
|
+
"stroke-linejoin": "round"
|
|
150
|
+
},
|
|
151
|
+
"menu": {
|
|
152
|
+
"viewBox": "0 0 24 24",
|
|
153
|
+
"fill": "none",
|
|
154
|
+
"stroke": "currentColor",
|
|
155
|
+
"stroke-width": "2",
|
|
156
|
+
"stroke-linecap": "round",
|
|
157
|
+
"stroke-linejoin": "round"
|
|
158
|
+
},
|
|
159
|
+
"named-slots": {
|
|
160
|
+
"viewBox": "0 0 24 24",
|
|
161
|
+
"fill": "none",
|
|
162
|
+
"stroke": "currentColor",
|
|
163
|
+
"stroke-width": "2",
|
|
164
|
+
"stroke-linecap": "round",
|
|
165
|
+
"stroke-linejoin": "round"
|
|
166
|
+
},
|
|
167
|
+
"pencil": {
|
|
168
|
+
"viewBox": "0 0 24 24",
|
|
169
|
+
"fill": "none",
|
|
170
|
+
"stroke": "currentColor",
|
|
171
|
+
"stroke-width": "2",
|
|
172
|
+
"stroke-linecap": "round",
|
|
173
|
+
"stroke-linejoin": "round"
|
|
174
|
+
},
|
|
175
|
+
"plus": {
|
|
176
|
+
"viewBox": "0 0 24 24",
|
|
177
|
+
"fill": "none",
|
|
178
|
+
"stroke": "currentColor",
|
|
179
|
+
"stroke-width": "2",
|
|
180
|
+
"stroke-linecap": "round",
|
|
181
|
+
"stroke-linejoin": "round"
|
|
182
|
+
},
|
|
183
|
+
"redo": {
|
|
184
|
+
"viewBox": "0 0 24 24",
|
|
185
|
+
"fill": "none",
|
|
186
|
+
"stroke": "currentColor",
|
|
187
|
+
"stroke-width": "2",
|
|
188
|
+
"stroke-linecap": "round",
|
|
189
|
+
"stroke-linejoin": "round"
|
|
190
|
+
},
|
|
191
|
+
"search": {
|
|
192
|
+
"viewBox": "0 0 24 24",
|
|
193
|
+
"fill": "none",
|
|
194
|
+
"stroke": "currentColor",
|
|
195
|
+
"stroke-width": "2",
|
|
196
|
+
"stroke-linecap": "round",
|
|
197
|
+
"stroke-linejoin": "round"
|
|
198
|
+
},
|
|
199
|
+
"sliders": {
|
|
200
|
+
"width": "24",
|
|
201
|
+
"height": "24",
|
|
202
|
+
"viewBox": "0 0 24 24",
|
|
203
|
+
"fill": "none",
|
|
204
|
+
"stroke": "currentColor",
|
|
205
|
+
"stroke-width": "2",
|
|
206
|
+
"stroke-linecap": "round",
|
|
207
|
+
"stroke-linejoin": "round"
|
|
208
|
+
},
|
|
209
|
+
"slot": {
|
|
210
|
+
"viewBox": "0 0 24 24",
|
|
211
|
+
"fill": "none",
|
|
212
|
+
"stroke": "currentColor",
|
|
213
|
+
"stroke-width": "2",
|
|
214
|
+
"stroke-linecap": "round",
|
|
215
|
+
"stroke-linejoin": "round"
|
|
216
|
+
},
|
|
217
|
+
"strikethrough": {
|
|
218
|
+
"viewBox": "0 0 24 24",
|
|
219
|
+
"fill": "none",
|
|
220
|
+
"stroke": "currentColor",
|
|
221
|
+
"stroke-width": "2",
|
|
222
|
+
"stroke-linecap": "round",
|
|
223
|
+
"stroke-linejoin": "round"
|
|
224
|
+
},
|
|
225
|
+
"table": {
|
|
226
|
+
"viewBox": "0 0 24 24",
|
|
227
|
+
"fill": "none"
|
|
228
|
+
},
|
|
229
|
+
"trash": {
|
|
230
|
+
"viewBox": "0 0 24 24",
|
|
231
|
+
"fill": "none",
|
|
232
|
+
"stroke": "currentColor",
|
|
233
|
+
"stroke-width": "2",
|
|
234
|
+
"stroke-linecap": "round",
|
|
235
|
+
"stroke-linejoin": "round"
|
|
236
|
+
},
|
|
237
|
+
"underline": {
|
|
238
|
+
"viewBox": "0 0 24 24",
|
|
239
|
+
"fill": "none",
|
|
240
|
+
"stroke": "currentColor",
|
|
241
|
+
"stroke-width": "2",
|
|
242
|
+
"stroke-linecap": "round",
|
|
243
|
+
"stroke-linejoin": "round"
|
|
244
|
+
},
|
|
245
|
+
"undo": {
|
|
246
|
+
"viewBox": "0 0 24 24",
|
|
247
|
+
"fill": "none",
|
|
248
|
+
"stroke": "currentColor",
|
|
249
|
+
"stroke-width": "2",
|
|
250
|
+
"stroke-linecap": "round",
|
|
251
|
+
"stroke-linejoin": "round"
|
|
252
|
+
},
|
|
253
|
+
"upload": {
|
|
254
|
+
"width": "24",
|
|
255
|
+
"height": "24",
|
|
256
|
+
"viewBox": "0 0 24 24",
|
|
257
|
+
"fill": "none",
|
|
258
|
+
"stroke": "currentColor",
|
|
259
|
+
"stroke-width": "2",
|
|
260
|
+
"stroke-linecap": "round",
|
|
261
|
+
"stroke-linejoin": "round"
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
//#endregion
|
|
265
|
+
//#region src/editor/components/VIcon.vue?vue&type=script&setup=true&lang.ts
|
|
266
|
+
var _hoisted_1$2 = ["innerHTML"];
|
|
267
|
+
//#endregion
|
|
268
|
+
//#region src/editor/components/VIcon.vue
|
|
269
|
+
var VIcon_default = /* @__PURE__ */ defineComponent({
|
|
270
|
+
__name: "VIcon",
|
|
271
|
+
props: { name: {} },
|
|
272
|
+
setup(__props) {
|
|
273
|
+
return (_ctx, _cache) => {
|
|
274
|
+
return openBlock(), createElementBlock("svg", mergeProps({ class: "vicon" }, unref(attrs)[__props.name], {
|
|
275
|
+
"aria-hidden": "true",
|
|
276
|
+
innerHTML: unref(contents)[__props.name]
|
|
277
|
+
}), null, 16, _hoisted_1$2);
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
//#endregion
|
|
282
|
+
//#region \0plugin-vue:export-helper
|
|
283
|
+
var _plugin_vue_export_helper_default = (sfc, props) => {
|
|
284
|
+
const target = sfc.__vccOpts || sfc;
|
|
285
|
+
for (const [key, val] of props) target[key] = val;
|
|
286
|
+
return target;
|
|
287
|
+
};
|
|
288
|
+
//#endregion
|
|
289
|
+
//#region src/editor/ui/dialog.ts
|
|
290
|
+
var dialogKey = Symbol("mech-dialog");
|
|
291
|
+
/** Create the reactive dialog store (provided once by the editor shell). */
|
|
292
|
+
function createDialogStore() {
|
|
293
|
+
const stack = shallowReactive([]);
|
|
294
|
+
let nextId = 0;
|
|
295
|
+
return {
|
|
296
|
+
stack,
|
|
297
|
+
open(component, props) {
|
|
298
|
+
stack.push({
|
|
299
|
+
id: ++nextId,
|
|
300
|
+
component,
|
|
301
|
+
props
|
|
302
|
+
});
|
|
303
|
+
},
|
|
304
|
+
back() {
|
|
305
|
+
stack.pop();
|
|
306
|
+
},
|
|
307
|
+
close() {
|
|
308
|
+
stack.length = 0;
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
/** Access the dialog store from any component inside the editor. */
|
|
313
|
+
function useDialog() {
|
|
314
|
+
const store = inject(dialogKey);
|
|
315
|
+
if (!store) throw new Error("[mechanica] useDialog used outside the editor");
|
|
316
|
+
return store;
|
|
317
|
+
}
|
|
318
|
+
//#endregion
|
|
319
|
+
//#region src/editor/ui/VDialog.vue?vue&type=script&setup=true&lang.ts
|
|
320
|
+
var _hoisted_1$1 = { class: "mech-modal__header" };
|
|
321
|
+
var _hoisted_2$1 = { class: "mech-modal__title" };
|
|
322
|
+
var _hoisted_3$1 = { class: "mech-modal__body" };
|
|
323
|
+
var _hoisted_4$1 = {
|
|
324
|
+
key: 0,
|
|
325
|
+
class: "mech-modal__actions"
|
|
326
|
+
};
|
|
327
|
+
//#endregion
|
|
328
|
+
//#region src/editor/ui/VDialog.vue
|
|
329
|
+
var VDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
|
|
330
|
+
__name: "VDialog",
|
|
331
|
+
props: {
|
|
332
|
+
title: {},
|
|
333
|
+
size: { default: "standard" }
|
|
334
|
+
},
|
|
335
|
+
setup(__props) {
|
|
336
|
+
const dialog = useDialog();
|
|
337
|
+
return (_ctx, _cache) => {
|
|
338
|
+
return openBlock(), createElementBlock("div", {
|
|
339
|
+
class: normalizeClass(["mech-modal", `mech-modal--${__props.size}`]),
|
|
340
|
+
role: "dialog",
|
|
341
|
+
"aria-modal": "true",
|
|
342
|
+
"data-mech-ui": ""
|
|
343
|
+
}, [
|
|
344
|
+
createElementVNode("header", _hoisted_1$1, [createElementVNode("h2", _hoisted_2$1, [renderSlot(_ctx.$slots, "header", {}, () => [createTextVNode(toDisplayString(__props.title), 1)], true)]), createElementVNode("button", {
|
|
345
|
+
type: "button",
|
|
346
|
+
class: "mech-modal__close",
|
|
347
|
+
"aria-label": "Close",
|
|
348
|
+
onClick: _cache[0] || (_cache[0] = ($event) => unref(dialog).back())
|
|
349
|
+
}, [createVNode(VIcon_default, { name: "close" })])]),
|
|
350
|
+
createElementVNode("div", _hoisted_3$1, [renderSlot(_ctx.$slots, "default", {}, void 0, true)]),
|
|
351
|
+
_ctx.$slots.actions ? (openBlock(), createElementBlock("footer", _hoisted_4$1, [renderSlot(_ctx.$slots, "actions", {}, void 0, true)])) : createCommentVNode("", true)
|
|
352
|
+
], 2);
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
}), [["__scopeId", "data-v-04d89005"]]);
|
|
356
|
+
//#endregion
|
|
357
|
+
//#region src/editor/dialogs/ImagePickerDialog.vue?vue&type=script&setup=true&lang.ts
|
|
358
|
+
var _hoisted_1 = { class: "mech-image-picker" };
|
|
359
|
+
var _hoisted_2 = { class: "mech-image-picker__upload-text" };
|
|
360
|
+
var _hoisted_3 = {
|
|
361
|
+
key: 0,
|
|
362
|
+
class: "mech-image-picker__grid"
|
|
363
|
+
};
|
|
364
|
+
var _hoisted_4 = ["title", "onClick"];
|
|
365
|
+
var _hoisted_5 = ["src", "alt"];
|
|
366
|
+
var _hoisted_6 = {
|
|
367
|
+
key: 1,
|
|
368
|
+
class: "mech-image-picker__empty"
|
|
369
|
+
};
|
|
370
|
+
//#endregion
|
|
371
|
+
//#region src/editor/dialogs/ImagePickerDialog.vue
|
|
372
|
+
var ImagePickerDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
|
|
373
|
+
__name: "ImagePickerDialog",
|
|
374
|
+
props: { onSelect: { type: Function } },
|
|
375
|
+
setup(__props) {
|
|
376
|
+
const props = __props;
|
|
377
|
+
const dialog = useDialog();
|
|
378
|
+
const uploader = inject("mechFileUploader", null);
|
|
379
|
+
const library = inject("mechImageLibrary", null);
|
|
380
|
+
const images = ref([]);
|
|
381
|
+
const loaded = ref(false);
|
|
382
|
+
const busy = ref(false);
|
|
383
|
+
const dragover = ref(false);
|
|
384
|
+
onMounted(load);
|
|
385
|
+
async function load() {
|
|
386
|
+
try {
|
|
387
|
+
if (library) images.value = await library();
|
|
388
|
+
} catch {} finally {
|
|
389
|
+
loaded.value = true;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
function select(value) {
|
|
393
|
+
props.onSelect(value);
|
|
394
|
+
dialog.back();
|
|
395
|
+
}
|
|
396
|
+
async function upload(file) {
|
|
397
|
+
if (!uploader || busy.value) return;
|
|
398
|
+
busy.value = true;
|
|
399
|
+
try {
|
|
400
|
+
const result = await uploader(file);
|
|
401
|
+
select({
|
|
402
|
+
src: result.src,
|
|
403
|
+
previewSrc: result.previewSrc ?? result.src
|
|
404
|
+
});
|
|
405
|
+
} finally {
|
|
406
|
+
busy.value = false;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
const onPick = (event) => {
|
|
410
|
+
const file = event.target.files?.[0];
|
|
411
|
+
if (file) upload(file);
|
|
412
|
+
};
|
|
413
|
+
const onDrop = (event) => {
|
|
414
|
+
dragover.value = false;
|
|
415
|
+
const file = event.dataTransfer?.files?.[0];
|
|
416
|
+
if (file) upload(file);
|
|
417
|
+
};
|
|
418
|
+
return (_ctx, _cache) => {
|
|
419
|
+
return openBlock(), createBlock(VDialog_default, {
|
|
420
|
+
title: "Choose image",
|
|
421
|
+
size: "wide"
|
|
422
|
+
}, {
|
|
423
|
+
actions: withCtx(() => [createElementVNode("button", {
|
|
424
|
+
type: "button",
|
|
425
|
+
class: "mech-button",
|
|
426
|
+
onClick: _cache[2] || (_cache[2] = ($event) => unref(dialog).back())
|
|
427
|
+
}, "Back")]),
|
|
428
|
+
default: withCtx(() => [createElementVNode("div", _hoisted_1, [
|
|
429
|
+
createElementVNode("label", {
|
|
430
|
+
class: normalizeClass(["mech-image-picker__upload", { "is-dragover": dragover.value }]),
|
|
431
|
+
onDragover: _cache[0] || (_cache[0] = withModifiers(($event) => dragover.value = true, ["prevent"])),
|
|
432
|
+
onDragleave: _cache[1] || (_cache[1] = ($event) => dragover.value = false),
|
|
433
|
+
onDrop: withModifiers(onDrop, ["prevent"])
|
|
434
|
+
}, [
|
|
435
|
+
createElementVNode("input", {
|
|
436
|
+
class: "mech-image-picker__file",
|
|
437
|
+
type: "file",
|
|
438
|
+
accept: "image/*",
|
|
439
|
+
onChange: onPick
|
|
440
|
+
}, null, 32),
|
|
441
|
+
createVNode(VIcon_default, {
|
|
442
|
+
name: "upload",
|
|
443
|
+
class: "mech-image-picker__upload-glyph"
|
|
444
|
+
}),
|
|
445
|
+
createElementVNode("span", _hoisted_2, toDisplayString(busy.value ? "Uploading…" : "Drop an image here, or click to upload"), 1)
|
|
446
|
+
], 34),
|
|
447
|
+
_cache[3] || (_cache[3] = createElementVNode("div", { class: "mech-image-picker__lib-head" }, "Project images", -1)),
|
|
448
|
+
images.value.length ? (openBlock(), createElementBlock("div", _hoisted_3, [(openBlock(true), createElementBlock(Fragment, null, renderList(images.value, (img) => {
|
|
449
|
+
return openBlock(), createElementBlock("button", {
|
|
450
|
+
key: img.id,
|
|
451
|
+
type: "button",
|
|
452
|
+
class: "mech-image-picker__item",
|
|
453
|
+
title: img.name,
|
|
454
|
+
onClick: ($event) => select({ src: img.src })
|
|
455
|
+
}, [createElementVNode("img", {
|
|
456
|
+
src: img.src,
|
|
457
|
+
alt: img.name,
|
|
458
|
+
loading: "lazy"
|
|
459
|
+
}, null, 8, _hoisted_5)], 8, _hoisted_4);
|
|
460
|
+
}), 128))])) : (openBlock(), createElementBlock("p", _hoisted_6, toDisplayString(loaded.value ? "No images uploaded yet — upload one above." : "Loading…"), 1))
|
|
461
|
+
])]),
|
|
462
|
+
_: 1
|
|
463
|
+
});
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
}), [["__scopeId", "data-v-ce3974a0"]]);
|
|
467
|
+
//#endregion
|
|
468
|
+
export { useDialog as a, dialogKey as i, VDialog_default as n, _plugin_vue_export_helper_default as o, createDialogStore as r, VIcon_default as s, ImagePickerDialog_default as t };
|