@blokkli/editor 2.0.0-alpha.59 → 2.0.0-alpha.60
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/dist/module.json +1 -1
- package/dist/module.mjs +28 -11
- package/dist/modules/agent/runtime/app/tools/auto_translate_paragraphs/Component.d.vue.ts +29 -0
- package/dist/modules/agent/runtime/app/tools/auto_translate_paragraphs/Component.vue +172 -0
- package/dist/modules/agent/runtime/app/tools/auto_translate_paragraphs/Component.vue.d.ts +29 -0
- package/dist/modules/agent/runtime/app/tools/auto_translate_paragraphs/index.d.ts +19 -0
- package/dist/modules/agent/runtime/app/tools/auto_translate_paragraphs/index.js +80 -0
- package/dist/modules/agent/runtime/app/tools/delegate_text_rewrite/Component.vue +16 -0
- package/dist/modules/agent/runtime/app/tools/get_all_page_content/index.js +1 -1
- package/dist/modules/agent/runtime/app/tools/get_content_fields/index.js +12 -9
- package/dist/modules/agent/runtime/app/tools/get_page_text/index.d.ts +2 -0
- package/dist/modules/agent/runtime/app/tools/get_page_text/index.js +65 -0
- package/dist/modules/agent/runtime/app/tools/get_referenced_entities/index.d.ts +2 -0
- package/dist/modules/agent/runtime/app/tools/get_referenced_entities/index.js +62 -0
- package/dist/modules/agent/runtime/app/tools/helpers.d.ts +8 -2
- package/dist/modules/agent/runtime/app/tools/helpers.js +9 -9
- package/dist/modules/agent/runtime/app/tools/schemas.d.ts +12 -0
- package/dist/modules/agent/runtime/app/tools/schemas.js +20 -0
- package/dist/modules/agent/runtime/app/tools/search_media/index.js +1 -1
- package/dist/modules/agent/runtime/app/tools/select_media/Component.vue +1 -1
- package/dist/modules/agent/runtime/server/agent.js +0 -1
- package/dist/modules/agent/runtime/server/classes/Session/index.js +4 -0
- package/dist/modules/agent/runtime/shared/toolResult.d.ts +4 -0
- package/dist/modules/agent/runtime/shared/toolResult.js +5 -0
- package/dist/modules/drupal/graphql/features/notifications.graphql +39 -0
- package/dist/modules/drupal/index.mjs +6 -1
- package/dist/modules/drupal/runtime/adapter/index.js +38 -0
- package/dist/runtime/editor/components/Actions/ItemDropdown/Item.vue +0 -1
- package/dist/runtime/editor/components/Actions/ScrollArrow/index.d.vue.ts +13 -0
- package/dist/runtime/editor/components/Actions/ScrollArrow/index.vue +52 -0
- package/dist/runtime/editor/components/Actions/ScrollArrow/index.vue.d.ts +13 -0
- package/dist/runtime/editor/components/Actions/Title/index.vue +2 -2
- package/dist/runtime/editor/components/Actions/index.vue +47 -7
- package/dist/runtime/editor/components/Actions/useToolbarScroll.d.ts +25 -0
- package/dist/runtime/editor/components/Actions/useToolbarScroll.js +125 -0
- package/dist/runtime/editor/components/AddListItem/index.vue +0 -2
- package/dist/runtime/editor/components/AppMenu/MenuButton.vue +1 -3
- package/dist/runtime/editor/components/ArtboardTooltip/index.vue +4 -1
- package/dist/runtime/editor/components/Avatar/index.vue +0 -1
- package/dist/runtime/editor/components/BlockPreviewRenderer/index.d.vue.ts +1 -1
- package/dist/runtime/editor/components/BlockPreviewRenderer/index.vue.d.ts +1 -1
- package/dist/runtime/editor/components/BundleSelector/index.vue +0 -4
- package/dist/runtime/editor/components/Dialog/index.d.vue.ts +2 -2
- package/dist/runtime/editor/components/Dialog/index.vue +1 -3
- package/dist/runtime/editor/components/Dialog/index.vue.d.ts +2 -2
- package/dist/runtime/editor/components/DiffApproval/Highlight/Item.d.vue.ts +8 -0
- package/dist/runtime/editor/components/DiffApproval/Highlight/Item.vue +12 -2
- package/dist/runtime/editor/components/DiffApproval/Highlight/Item.vue.d.ts +8 -0
- package/dist/runtime/editor/components/DiffApproval/Highlight/index.d.vue.ts +8 -0
- package/dist/runtime/editor/components/DiffApproval/Highlight/index.vue +14 -2
- package/dist/runtime/editor/components/DiffApproval/Highlight/index.vue.d.ts +8 -0
- package/dist/runtime/editor/components/DiffApproval/Toolbar/index.d.vue.ts +2 -2
- package/dist/runtime/editor/components/DiffApproval/Toolbar/index.vue +0 -2
- package/dist/runtime/editor/components/DiffApproval/Toolbar/index.vue.d.ts +2 -2
- package/dist/runtime/editor/components/DiffApproval/index.vue +1 -0
- package/dist/runtime/editor/components/Form/Datepicker/index.vue +0 -1
- package/dist/runtime/editor/components/Form/TextDark/index.vue +0 -1
- package/dist/runtime/editor/components/Form/Textarea/index.vue +0 -1
- package/dist/runtime/editor/components/Form/Toggle/index.d.vue.ts +1 -0
- package/dist/runtime/editor/components/Form/Toggle/index.vue +9 -2
- package/dist/runtime/editor/components/Form/Toggle/index.vue.d.ts +1 -0
- package/dist/runtime/editor/components/FormOverlay/index.vue +0 -1
- package/dist/runtime/editor/components/Icon/index.vue +0 -2
- package/dist/runtime/editor/components/Messages/Item/index.vue +4 -1
- package/dist/runtime/editor/components/Messages/index.vue +3 -0
- package/dist/runtime/editor/components/Panel/Sheet/index.vue +1 -1
- package/dist/runtime/editor/components/Popup/index.vue +0 -2
- package/dist/runtime/editor/components/RichText/Editor/index.d.vue.ts +1 -1
- package/dist/runtime/editor/components/RichText/Editor/index.vue.d.ts +1 -1
- package/dist/runtime/editor/components/ScheduleDate/index.vue +1 -3
- package/dist/runtime/editor/components/SearchOverlay/index.d.vue.ts +1 -1
- package/dist/runtime/editor/components/SearchOverlay/index.vue.d.ts +1 -1
- package/dist/runtime/editor/components/Toolbar/ViewOptions/List/Button/index.d.vue.ts +3 -0
- package/dist/runtime/editor/components/Toolbar/ViewOptions/List/Button/index.vue +74 -0
- package/dist/runtime/editor/components/Toolbar/ViewOptions/List/Button/index.vue.d.ts +3 -0
- package/dist/runtime/editor/components/Toolbar/ViewOptions/List/index.d.vue.ts +7 -0
- package/dist/runtime/editor/components/Toolbar/ViewOptions/List/index.vue +16 -0
- package/dist/runtime/editor/components/Toolbar/ViewOptions/List/index.vue.d.ts +7 -0
- package/dist/runtime/editor/components/Toolbar/ViewOptions/index.d.vue.ts +3 -0
- package/dist/runtime/editor/components/Toolbar/ViewOptions/index.vue +57 -0
- package/dist/runtime/editor/components/Toolbar/ViewOptions/index.vue.d.ts +3 -0
- package/dist/runtime/editor/components/Toolbar/index.vue +3 -56
- package/dist/runtime/editor/components/ToolbarDropdown/index.d.vue.ts +21 -0
- package/dist/runtime/editor/components/ToolbarDropdown/index.vue +36 -0
- package/dist/runtime/editor/components/ToolbarDropdown/index.vue.d.ts +21 -0
- package/dist/runtime/editor/components/Tooltip/Context.vue +3 -1
- package/dist/runtime/editor/components/Tooltip/index.d.vue.ts +1 -1
- package/dist/runtime/editor/components/Tooltip/index.vue +4 -1
- package/dist/runtime/editor/components/Tooltip/index.vue.d.ts +1 -1
- package/dist/runtime/editor/components/index.d.ts +1 -0
- package/dist/runtime/editor/components/index.js +1 -0
- package/dist/runtime/editor/composables/defineViewOption.d.ts +5 -0
- package/dist/runtime/editor/composables/defineViewOption.js +10 -0
- package/dist/runtime/editor/composables/index.d.ts +3 -0
- package/dist/runtime/editor/composables/index.js +2 -0
- package/dist/runtime/editor/composables/useDismiss.d.ts +30 -0
- package/dist/runtime/editor/composables/useDismiss.js +43 -0
- package/dist/runtime/editor/composables/useGlobalBlokkliObject.d.ts +3 -3
- package/dist/runtime/editor/css/output.css +1 -1
- package/dist/runtime/editor/events/index.d.ts +23 -0
- package/dist/runtime/editor/features/add-list/Actions/index.vue +0 -1
- package/dist/runtime/editor/features/add-list/Blocks/index.vue +0 -1
- package/dist/runtime/editor/features/add-list/Help/Item.vue +2 -7
- package/dist/runtime/editor/features/add-list/Help/index.vue +1 -1
- package/dist/runtime/editor/features/add-list/index.vue +0 -2
- package/dist/runtime/editor/features/anchors/index.vue +11 -11
- package/dist/runtime/editor/features/anchors/types.d.ts +1 -0
- package/dist/runtime/editor/features/anchors/types.js +1 -0
- package/dist/runtime/editor/features/artboard/Renderer.vue +30 -28
- package/dist/runtime/editor/features/block-scheduler/Dialog/ScheduleSection.vue +0 -3
- package/dist/runtime/editor/features/block-scheduler/index.vue +0 -1
- package/dist/runtime/editor/features/block-transfer/SummaryDialog/index.vue +0 -4
- package/dist/runtime/editor/features/breadcrumbs/Crumb/index.vue +0 -5
- package/dist/runtime/editor/features/changelog/changelog.json +8 -0
- package/dist/runtime/editor/features/command-palette/Palette/Item/index.vue +0 -3
- package/dist/runtime/editor/features/command-palette/Palette/index.vue +0 -1
- package/dist/runtime/editor/features/comments/AddForm/index.vue +0 -1
- package/dist/runtime/editor/features/comments/Comment/Actions/index.vue +0 -4
- package/dist/runtime/editor/features/comments/Comment/index.d.vue.ts +14 -0
- package/dist/runtime/editor/features/comments/Comment/index.vue +29 -8
- package/dist/runtime/editor/features/comments/Comment/index.vue.d.ts +14 -0
- package/dist/runtime/editor/features/comments/CommentInput/index.d.vue.ts +1 -1
- package/dist/runtime/editor/features/comments/CommentInput/index.vue +0 -3
- package/dist/runtime/editor/features/comments/CommentInput/index.vue.d.ts +1 -1
- package/dist/runtime/editor/features/comments/Sidebar/AddForm/index.vue +0 -1
- package/dist/runtime/editor/features/comments/Sidebar/index.d.vue.ts +16 -0
- package/dist/runtime/editor/features/comments/Sidebar/index.vue +13 -8
- package/dist/runtime/editor/features/comments/Sidebar/index.vue.d.ts +16 -0
- package/dist/runtime/editor/features/comments/Thread/ReplyForm/index.vue +0 -1
- package/dist/runtime/editor/features/comments/Thread/index.d.vue.ts +16 -0
- package/dist/runtime/editor/features/comments/Thread/index.vue +26 -6
- package/dist/runtime/editor/features/comments/Thread/index.vue.d.ts +16 -0
- package/dist/runtime/editor/features/comments/index.vue +28 -3
- package/dist/runtime/editor/features/delete/types.d.ts +1 -0
- package/dist/runtime/editor/features/delete/types.js +1 -0
- package/dist/runtime/editor/features/dev-mode/index.vue +17 -15
- package/dist/runtime/editor/features/dragging-overlay/DragItems/index.vue +1 -0
- package/dist/runtime/editor/features/duplicate/types.d.ts +1 -0
- package/dist/runtime/editor/features/duplicate/types.js +1 -0
- package/dist/runtime/editor/features/editable-field/Overlay/Frame/index.vue +0 -2
- package/dist/runtime/editor/features/editable-field/Overlay/Plaintext/index.vue +0 -1
- package/dist/runtime/editor/features/editable-field/Overlay/ReadabilityIndicator/index.vue +0 -5
- package/dist/runtime/editor/features/editable-field/Overlay/index.vue +0 -5
- package/dist/runtime/editor/features/editable-mask/index.vue +21 -20
- package/dist/runtime/editor/features/entity-title/index.vue +0 -4
- package/dist/runtime/editor/features/fragments/Dialog/index.vue +0 -4
- package/dist/runtime/editor/features/grid/index.vue +16 -15
- package/dist/runtime/editor/features/grid/types.d.ts +1 -0
- package/dist/runtime/editor/features/grid/types.js +1 -0
- package/dist/runtime/editor/features/help/Dialog/index.d.vue.ts +7 -0
- package/dist/runtime/editor/features/help/Dialog/index.vue +57 -0
- package/dist/runtime/editor/features/help/Dialog/index.vue.d.ts +7 -0
- package/dist/runtime/editor/features/help/index.vue +52 -47
- package/dist/runtime/editor/features/history/List/index.vue +2 -9
- package/dist/runtime/editor/features/history/types.d.ts +1 -0
- package/dist/runtime/editor/features/history/types.js +1 -0
- package/dist/runtime/editor/features/notifications/Item/index.d.vue.ts +4 -0
- package/dist/runtime/editor/features/notifications/Item/index.vue +96 -0
- package/dist/runtime/editor/features/notifications/Item/index.vue.d.ts +4 -0
- package/dist/runtime/editor/features/notifications/List/index.d.vue.ts +11 -0
- package/dist/runtime/editor/features/notifications/List/index.vue +126 -0
- package/dist/runtime/editor/features/notifications/List/index.vue.d.ts +11 -0
- package/dist/runtime/editor/features/notifications/docs.md +12 -0
- package/dist/runtime/editor/features/notifications/index.d.vue.ts +3 -0
- package/dist/runtime/editor/features/notifications/index.vue +123 -0
- package/dist/runtime/editor/features/notifications/index.vue.d.ts +3 -0
- package/dist/runtime/editor/features/notifications/types.d.ts +132 -0
- package/dist/runtime/editor/features/notifications/types.js +20 -0
- package/dist/runtime/editor/features/options/Form/Checkbox/index.vue +6 -2
- package/dist/runtime/editor/features/options/Form/Checkboxes/index.vue +14 -4
- package/dist/runtime/editor/features/options/Form/Color/index.vue +1 -1
- package/dist/runtime/editor/features/options/Form/ComplexType/index.vue +0 -1
- package/dist/runtime/editor/features/options/Form/DateTimeLocal/index.vue +0 -1
- package/dist/runtime/editor/features/options/Form/Group.vue +3 -1
- package/dist/runtime/editor/features/options/Form/Item.vue +1 -2
- package/dist/runtime/editor/features/options/Form/Number/index.vue +9 -3
- package/dist/runtime/editor/features/options/Form/Radios/index.vue +3 -2
- package/dist/runtime/editor/features/options/Form/Range/index.vue +8 -2
- package/dist/runtime/editor/features/options/Form/Text/index.vue +6 -2
- package/dist/runtime/editor/features/options/index.vue +7 -1
- package/dist/runtime/editor/features/ownership/Banner/index.vue +3 -1
- package/dist/runtime/editor/features/ownership/types.d.ts +1 -0
- package/dist/runtime/editor/features/ownership/types.js +1 -0
- package/dist/runtime/editor/features/preview-grant/types.d.ts +1 -0
- package/dist/runtime/editor/features/preview-grant/types.js +1 -0
- package/dist/runtime/editor/features/proxy-view/index.vue +24 -21
- package/dist/runtime/editor/features/publish/Dialog/PublishOption.vue +0 -2
- package/dist/runtime/editor/features/publish/Dialog/index.vue +1 -2
- package/dist/runtime/editor/features/responsive-preview/Frame/index.vue +0 -1
- package/dist/runtime/editor/features/revert/types.d.ts +1 -0
- package/dist/runtime/editor/features/revert/types.js +1 -0
- package/dist/runtime/editor/features/settings/Dialog/FeatureSetting/index.vue +18 -8
- package/dist/runtime/editor/features/swap/types.d.ts +1 -0
- package/dist/runtime/editor/features/swap/types.js +1 -0
- package/dist/runtime/editor/features/translations/Banner/index.vue +4 -1
- package/dist/runtime/editor/features/translations/CsvDialog/Import/index.vue +4 -1
- package/dist/runtime/editor/features/translations/TranslateDialog/index.vue +7 -2
- package/dist/runtime/editor/plugins/BlockIndicator/index.vue +0 -2
- package/dist/runtime/editor/plugins/ContextMenu/Menu/index.vue +4 -36
- package/dist/runtime/editor/plugins/ItemAction/index.vue +0 -1
- package/dist/runtime/editor/plugins/Sidebar/index.vue +7 -50
- package/dist/runtime/editor/plugins/ToolbarButton/index.d.vue.ts +8 -2
- package/dist/runtime/editor/plugins/ToolbarButton/index.vue +122 -28
- package/dist/runtime/editor/plugins/ToolbarButton/index.vue.d.ts +8 -2
- package/dist/runtime/editor/plugins/index.d.ts +1 -2
- package/dist/runtime/editor/plugins/index.js +1 -3
- package/dist/runtime/editor/providers/fieldValue.js +11 -13
- package/dist/runtime/editor/providers/plugin.d.ts +12 -0
- package/dist/runtime/editor/providers/plugin.js +9 -0
- package/dist/runtime/editor/translations/de.json +51 -19
- package/dist/runtime/editor/translations/fr.json +16 -4
- package/dist/runtime/editor/translations/gsw_CH.json +44 -19
- package/dist/runtime/editor/translations/it.json +16 -4
- package/package.json +4 -5
- package/dist/runtime/editor/plugins/ViewOption/index.d.vue.ts +0 -139
- package/dist/runtime/editor/plugins/ViewOption/index.vue +0 -99
- package/dist/runtime/editor/plugins/ViewOption/index.vue.d.ts +0 -139
|
@@ -77,8 +77,14 @@ export declare function resolveHost(app: BlokkliApp, uuid: string): {
|
|
|
77
77
|
*/
|
|
78
78
|
export declare function getResolvedOptions(app: BlokkliApp, bundleOrBlock: Parameters<BlokkliApp['definitions']['getBlockDefinition']>[0], fieldListType: Parameters<BlokkliApp['definitions']['getBlockDefinition']>[1], parentBundle: Parameters<BlokkliApp['definitions']['getBlockDefinition']>[2]): OptionItem[] | null;
|
|
79
79
|
/**
|
|
80
|
-
* Read every editable content field of a block (or entity), skipping
|
|
81
|
-
*
|
|
80
|
+
* Read every editable content field of a block (or entity), skipping `table`
|
|
81
|
+
* fields (no text payload). Iterates the declared `editableFieldConfig` rather
|
|
82
|
+
* than the runtime `v-blokkli-editable` directive registry — the former is the
|
|
83
|
+
* canonical declaration (it sees fields exposed via `propsFieldMapping` even
|
|
84
|
+
* when no directive is present in the template), while the latter only sees
|
|
85
|
+
* fields whose template marks them with the directive. `fieldValue.readValue`
|
|
86
|
+
* already knows how to resolve a value through `propsFieldMapping`, so this
|
|
87
|
+
* one swap surfaces all editable fields to every caller.
|
|
82
88
|
*/
|
|
83
89
|
export declare function readBlockContentFields(app: BlokkliApp, uuid: string, entityType: string, bundle: string): Array<{
|
|
84
90
|
fieldName: string;
|
|
@@ -257,21 +257,21 @@ export function getResolvedOptions(app, bundleOrBlock, fieldListType, parentBund
|
|
|
257
257
|
}
|
|
258
258
|
export function readBlockContentFields(app, uuid, entityType, bundle) {
|
|
259
259
|
const result = [];
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
);
|
|
266
|
-
|
|
260
|
+
const configs = app.types.editableFieldConfig.forEntityTypeAndBundle(
|
|
261
|
+
entityType,
|
|
262
|
+
bundle
|
|
263
|
+
);
|
|
264
|
+
for (const cfg of configs) {
|
|
265
|
+
if (cfg.type === "table") continue;
|
|
266
|
+
const fieldType = cfg.type === "frame" || cfg.type === "markup" ? "markup" : "plain";
|
|
267
267
|
const value = app.fieldValue.readValue(
|
|
268
268
|
entityType,
|
|
269
269
|
uuid,
|
|
270
270
|
bundle,
|
|
271
|
-
|
|
271
|
+
cfg.name,
|
|
272
272
|
fieldType
|
|
273
273
|
);
|
|
274
|
-
result.push({ fieldName:
|
|
274
|
+
result.push({ fieldName: cfg.name, fieldType, value });
|
|
275
275
|
}
|
|
276
276
|
return result;
|
|
277
277
|
}
|
|
@@ -60,6 +60,18 @@ export declare const mutationResultSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
60
60
|
* a single string is accepted as a fallback.
|
|
61
61
|
*/
|
|
62
62
|
export declare function stringArrayParam(description: string): z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>;
|
|
63
|
+
/**
|
|
64
|
+
* Wraps an object params schema to tolerate a singular key when the schema
|
|
65
|
+
* actually expects its plural form (e.g. `uuid` → `uuids`). LLMs — especially
|
|
66
|
+
* the smaller models — frequently pick the singular form when a tool
|
|
67
|
+
* description mentions both ("one or more UUIDs"). Without this, the call
|
|
68
|
+
* fails validation and the model often retries with the same wrong key.
|
|
69
|
+
*
|
|
70
|
+
* The generated JSON Schema is unchanged (the wrapping happens via
|
|
71
|
+
* `z.preprocess`), so the model is still guided to the plural form; the
|
|
72
|
+
* singular form is silently accepted as a fallback.
|
|
73
|
+
*/
|
|
74
|
+
export declare function tolerantSingularKeys<T extends z.ZodType>(schema: T, aliases: Record<string, string>): z.ZodPipe<z.ZodTransform<unknown, unknown>, T>;
|
|
63
75
|
/**
|
|
64
76
|
* Shared schema for option values (used by add_blocks and set_block_options).
|
|
65
77
|
*/
|
|
@@ -39,6 +39,26 @@ export function stringArrayParam(description) {
|
|
|
39
39
|
z.array(z.string()).describe(description)
|
|
40
40
|
);
|
|
41
41
|
}
|
|
42
|
+
export function tolerantSingularKeys(schema, aliases) {
|
|
43
|
+
return z.preprocess((value) => {
|
|
44
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
const obj = value;
|
|
48
|
+
const remapped = {};
|
|
49
|
+
let touched = false;
|
|
50
|
+
for (const key of Object.keys(obj)) {
|
|
51
|
+
const plural = aliases[key];
|
|
52
|
+
if (plural && !(plural in obj)) {
|
|
53
|
+
remapped[plural] = obj[key];
|
|
54
|
+
touched = true;
|
|
55
|
+
} else {
|
|
56
|
+
remapped[key] = obj[key];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return touched ? remapped : obj;
|
|
60
|
+
}, schema);
|
|
61
|
+
}
|
|
42
62
|
export const optionValueSchema = z.union([
|
|
43
63
|
z.string(),
|
|
44
64
|
z.boolean(),
|
|
@@ -2,7 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
|
|
3
3
|
const paramsSchema = z.object({
|
|
4
4
|
query: z.string().optional().describe(
|
|
5
|
-
|
|
5
|
+
'Search text to filter media items. Searching for "foobar test" will search the exact full string, so prefer searching single for words.'
|
|
6
6
|
),
|
|
7
7
|
bundle: z.string().optional().describe('Media bundle filter (e.g., "image", "video")')
|
|
8
8
|
});
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
@click="selectedId = item.mediaId"
|
|
15
15
|
>
|
|
16
16
|
<div
|
|
17
|
-
class="
|
|
17
|
+
class="_bk_size-100 _bk_bg-mono-100 _bk_rounded _bk_overflow-hidden _bk_shrink-0 _bk_flex _bk_items-center _bk_justify-center"
|
|
18
18
|
:class="{
|
|
19
19
|
'_bk_outline _bk_outline-accent-700 _bk_relative _bk_z-40': selectedId === item.mediaId
|
|
20
20
|
}"
|
|
@@ -231,6 +231,10 @@ export class Session {
|
|
|
231
231
|
}
|
|
232
232
|
newConversation(peer, authSecret) {
|
|
233
233
|
this.abortController?.abort();
|
|
234
|
+
for (const pending of this.pendingToolCalls.values()) {
|
|
235
|
+
pending.reject(new Error("Cancelled"));
|
|
236
|
+
}
|
|
237
|
+
this.pendingToolCalls.clear();
|
|
234
238
|
this.history.clear();
|
|
235
239
|
this.lastTools = [];
|
|
236
240
|
this.lastDebugPayload = null;
|
|
@@ -89,6 +89,10 @@ export declare class ToolResult {
|
|
|
89
89
|
/**
|
|
90
90
|
* Stale form: a volatile query whose data is outdated because a mutation
|
|
91
91
|
* happened after it. Pure and idempotent.
|
|
92
|
+
*
|
|
93
|
+
* Error results are preserved verbatim — a failed call isn't "stale data",
|
|
94
|
+
* it's a failure the LLM may still need to act on (e.g. fix its input and
|
|
95
|
+
* retry). Collapsing it to a generic stale summary hides the cause.
|
|
92
96
|
*/
|
|
93
97
|
stale(): ToolResult;
|
|
94
98
|
}
|
|
@@ -145,9 +145,14 @@ export class ToolResult {
|
|
|
145
145
|
/**
|
|
146
146
|
* Stale form: a volatile query whose data is outdated because a mutation
|
|
147
147
|
* happened after it. Pure and idempotent.
|
|
148
|
+
*
|
|
149
|
+
* Error results are preserved verbatim — a failed call isn't "stale data",
|
|
150
|
+
* it's a failure the LLM may still need to act on (e.g. fix its input and
|
|
151
|
+
* retry). Collapsing it to a generic stale summary hides the cause.
|
|
148
152
|
*/
|
|
149
153
|
stale() {
|
|
150
154
|
if (this.envelope.kind === "stale") return this;
|
|
155
|
+
if (this.envelope.kind === "error") return this;
|
|
151
156
|
return ToolResult.fromWire(
|
|
152
157
|
JSON.stringify({ stale: true, summary: this.staleSummary })
|
|
153
158
|
);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
fragment paragraphsBlokkliNotification on ParagraphsBlokkliNotification {
|
|
2
|
+
uuid
|
|
3
|
+
type
|
|
4
|
+
read
|
|
5
|
+
created
|
|
6
|
+
title
|
|
7
|
+
message
|
|
8
|
+
relatedEntityUuid
|
|
9
|
+
user {
|
|
10
|
+
id
|
|
11
|
+
name
|
|
12
|
+
imageUrl
|
|
13
|
+
}
|
|
14
|
+
host {
|
|
15
|
+
entityType
|
|
16
|
+
entityUuid
|
|
17
|
+
entityBundle
|
|
18
|
+
label
|
|
19
|
+
url
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
query pbGetNotifications($after: String, $markAsRead: Boolean) {
|
|
24
|
+
result: pbGetNotifications(after: $after, markAsRead: $markAsRead) {
|
|
25
|
+
items {
|
|
26
|
+
...paragraphsBlokkliNotification
|
|
27
|
+
}
|
|
28
|
+
unreadCount
|
|
29
|
+
nextCursor
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
query pbGetNotificationCount {
|
|
34
|
+
count: pbGetNotificationCount
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
mutation pbMarkNotificationsAsRead($uuids: [String!]) {
|
|
38
|
+
count: pbMarkNotificationsAsRead(uuids: $uuids)
|
|
39
|
+
}
|
|
@@ -163,11 +163,16 @@ export declare const templateEditRouteName: string|null
|
|
|
163
163
|
}
|
|
164
164
|
addMutation("ignore_analyze");
|
|
165
165
|
addMutation("unignore_analyze");
|
|
166
|
-
if (graphql.schemaHasType("
|
|
166
|
+
if (graphql.schemaHasType("ParagraphsBlokkliComment")) {
|
|
167
167
|
addGraphqlDocument("features/comments.graphql");
|
|
168
168
|
} else {
|
|
169
169
|
context.features.disableFeature("comments");
|
|
170
170
|
}
|
|
171
|
+
if (queryFields.has("pbGetNotifications") && queryFields.has("pbGetNotificationCount") && mutationFields.has("pbMarkNotificationsAsRead")) {
|
|
172
|
+
addGraphqlDocument("features/notifications.graphql");
|
|
173
|
+
} else {
|
|
174
|
+
context.features.disableFeature("notifications");
|
|
175
|
+
}
|
|
171
176
|
if (mutationFields.has("paragraphsBlokkliAgentToken")) {
|
|
172
177
|
addGraphqlDocument("features/agent.graphql");
|
|
173
178
|
} else {
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
useRouter
|
|
14
14
|
} from "#imports";
|
|
15
15
|
import { ParagraphsBlokkliRemoteVideoProvider } from "#graphql-operations";
|
|
16
|
+
import { toValidNotificationType } from "#blokkli/editor/features/notifications/types";
|
|
16
17
|
function mapBlokkliUser(user) {
|
|
17
18
|
if (!user) {
|
|
18
19
|
return null;
|
|
@@ -775,6 +776,43 @@ export default defineBlokkliEditAdapter(
|
|
|
775
776
|
return updated;
|
|
776
777
|
});
|
|
777
778
|
}
|
|
779
|
+
if (hasQuery("pbGetNotifications")) {
|
|
780
|
+
adapter.loadNotifications = (options) => useGraphqlQuery("pbGetNotifications", {
|
|
781
|
+
after: options.after,
|
|
782
|
+
markAsRead: options.markAsRead
|
|
783
|
+
}).then((v) => {
|
|
784
|
+
const result = v.data.result;
|
|
785
|
+
return {
|
|
786
|
+
items: (result?.items ?? []).map((item) => ({
|
|
787
|
+
uuid: item.uuid,
|
|
788
|
+
type: toValidNotificationType(item.type),
|
|
789
|
+
read: item.read,
|
|
790
|
+
created: item.created,
|
|
791
|
+
title: item.title,
|
|
792
|
+
message: item.message ?? void 0,
|
|
793
|
+
relatedEntityUuid: item.relatedEntityUuid ?? void 0,
|
|
794
|
+
user: mapBlokkliUser(item.user),
|
|
795
|
+
host: item.host ? {
|
|
796
|
+
uuid: item.host.entityUuid,
|
|
797
|
+
entityType: item.host.entityType,
|
|
798
|
+
entityBundle: item.host.entityBundle,
|
|
799
|
+
label: item.host.label ?? "",
|
|
800
|
+
url: item.host.url ?? ""
|
|
801
|
+
} : null
|
|
802
|
+
})),
|
|
803
|
+
nextCursor: result?.nextCursor ?? null,
|
|
804
|
+
unreadCount: result?.unreadCount ?? 0
|
|
805
|
+
};
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
if (hasQuery("pbGetNotificationCount")) {
|
|
809
|
+
adapter.loadUnreadNotificationsCount = () => useGraphqlQuery("pbGetNotificationCount").then((v) => v.data.count ?? 0);
|
|
810
|
+
}
|
|
811
|
+
if (hasMutation("pbMarkNotificationsAsRead")) {
|
|
812
|
+
adapter.markAllNotificationsAsRead = () => useGraphqlMutation("pbMarkNotificationsAsRead", {
|
|
813
|
+
uuids: void 0
|
|
814
|
+
}).then((v) => v.data.count);
|
|
815
|
+
}
|
|
778
816
|
if (hasQuery("pbReferencedEntities")) {
|
|
779
817
|
adapter.getReferencedEntities = (uuids) => useGraphqlQuery("pbReferencedEntities", {
|
|
780
818
|
...ctx.value,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<button
|
|
3
|
-
:data-test="`item-dropdown-action-${action.id}`"
|
|
4
3
|
class="_bk_gap-10 _bk_group/tooltip _bk_grid _bk_grid-cols-[20px_1fr] _bk_w-full _bk_text-mono-300 _bk_items-center _bk_left-left _bk_leading-none _bk_disabled:opacity-20 _bk_disabled:pointer-events-none _bk_hover:text-white _bk_hover:bg-mono-800 _bk_px-10"
|
|
5
4
|
:class="{
|
|
6
5
|
'_bk_hover:bg-orange-normal/10! _bk_hover:text-orange-light!': action.variant === 'agent',
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare const _default: typeof __VLS_export;
|
|
2
|
+
export default _default;
|
|
3
|
+
declare const __VLS_export: import("vue").DefineComponent<{
|
|
4
|
+
side: "left" | "right";
|
|
5
|
+
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
+
end: () => any;
|
|
7
|
+
start: () => any;
|
|
8
|
+
}, string, import("vue").PublicProps, Readonly<{
|
|
9
|
+
side: "left" | "right";
|
|
10
|
+
}> & Readonly<{
|
|
11
|
+
onEnd?: (() => any) | undefined;
|
|
12
|
+
onStart?: (() => any) | undefined;
|
|
13
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<button
|
|
3
|
+
type="button"
|
|
4
|
+
class="_bk_hidden _bk_lg:flex _bk_absolute _bk_top-1 _bk_bottom-1 _bk_z-actions _bk_w-40 _bk_cursor-pointer _bk_bg-mono-950/90 _bk_hover:bg-mono-700 _bk_items-center _bk_justify-center"
|
|
5
|
+
:class="
|
|
6
|
+
side === 'left' ? '_bk_left-0 _bk_border-r _bk_border-r-mono-700' : '_bk_right-0 _bk_border-l _bk_border-l-mono-700'
|
|
7
|
+
"
|
|
8
|
+
@pointerdown="onPointerDown"
|
|
9
|
+
>
|
|
10
|
+
<Icon
|
|
11
|
+
:name="
|
|
12
|
+
side === 'left' ? 'bk_mdi_chevron_backward' : 'bk_mdi_chevron_forward'
|
|
13
|
+
"
|
|
14
|
+
class="_bk_fill-current _bk_pointer-events-none _bk_size-30"
|
|
15
|
+
/>
|
|
16
|
+
</button>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script setup>
|
|
20
|
+
import { onBeforeUnmount } from "#imports";
|
|
21
|
+
import { Icon } from "#blokkli/editor/components";
|
|
22
|
+
defineProps({
|
|
23
|
+
side: { type: String, required: true }
|
|
24
|
+
});
|
|
25
|
+
const emit = defineEmits(["start", "end"]);
|
|
26
|
+
let isPressed = false;
|
|
27
|
+
function onRelease() {
|
|
28
|
+
if (!isPressed) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
isPressed = false;
|
|
32
|
+
window.removeEventListener("pointerup", onRelease);
|
|
33
|
+
window.removeEventListener("pointercancel", onRelease);
|
|
34
|
+
emit("end");
|
|
35
|
+
}
|
|
36
|
+
function onPointerDown() {
|
|
37
|
+
if (isPressed) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
isPressed = true;
|
|
41
|
+
window.addEventListener("pointerup", onRelease);
|
|
42
|
+
window.addEventListener("pointercancel", onRelease);
|
|
43
|
+
emit("start");
|
|
44
|
+
}
|
|
45
|
+
onBeforeUnmount(onRelease);
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<script>
|
|
49
|
+
export default {
|
|
50
|
+
name: "ActionsScrollArrow"
|
|
51
|
+
};
|
|
52
|
+
</script>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare const _default: typeof __VLS_export;
|
|
2
|
+
export default _default;
|
|
3
|
+
declare const __VLS_export: import("vue").DefineComponent<{
|
|
4
|
+
side: "left" | "right";
|
|
5
|
+
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
+
end: () => any;
|
|
7
|
+
start: () => any;
|
|
8
|
+
}, string, import("vue").PublicProps, Readonly<{
|
|
9
|
+
side: "left" | "right";
|
|
10
|
+
}> & Readonly<{
|
|
11
|
+
onEnd?: (() => any) | undefined;
|
|
12
|
+
onStart?: (() => any) | undefined;
|
|
13
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
}"
|
|
8
8
|
>
|
|
9
9
|
<button
|
|
10
|
-
data-test="item-actions-dropdown-toggle"
|
|
11
10
|
class="bk-blokkli-item-actions-type-button bk-item-icon-hover-parent _bk_group/tooltip _bk_pl-10 _bk_pr-3 _bk_flex _bk_items-center _bk_lg:min-w-[180px] _bk_text-mono-300 _bk_font-bold _bk_h-full _bk_leading-none _bk_relative _bk_w-full _bk_cursor-pointer _bk_hover:text-mono-50 _bk_hover:bg-mono-700"
|
|
12
11
|
tabindex="-1"
|
|
13
12
|
:class="{
|
|
@@ -106,7 +105,7 @@
|
|
|
106
105
|
</template>
|
|
107
106
|
|
|
108
107
|
<script setup>
|
|
109
|
-
import { watch, computed, useBlokkli } from "#imports";
|
|
108
|
+
import { watch, computed, nextTick, useBlokkli } from "#imports";
|
|
110
109
|
import { falsy } from "#blokkli/helpers";
|
|
111
110
|
import {
|
|
112
111
|
Icon,
|
|
@@ -147,6 +146,7 @@ async function onToggleDropdown() {
|
|
|
147
146
|
const willOpen = !showDropdown.value;
|
|
148
147
|
if (willOpen) {
|
|
149
148
|
await ui.flushPendingChanges();
|
|
149
|
+
await nextTick();
|
|
150
150
|
}
|
|
151
151
|
showDropdown.value = willOpen;
|
|
152
152
|
}
|
|
@@ -2,19 +2,27 @@
|
|
|
2
2
|
<div
|
|
3
3
|
ref="el"
|
|
4
4
|
:style="{
|
|
5
|
-
visibility: isVisible ? 'visible' : 'hidden'
|
|
5
|
+
visibility: isVisible ? 'visible' : 'hidden',
|
|
6
|
+
'--bk-actions-max-width': `${paddedViewportWidth}px`
|
|
6
7
|
}"
|
|
7
8
|
class="bk bk-blokkli-item-actions-inner _bk_absolute _bk_left-0 _bk_p-0 _bk_z-actions _bk_w-full _bk_text-mono-50 _bk_select-none _bk_text-sm _bk_pointer-events-auto"
|
|
8
9
|
@mouseleave="onMouseLeave"
|
|
9
10
|
@mouseenter="onMouseEnter"
|
|
10
11
|
>
|
|
12
|
+
<ScrollArrow
|
|
13
|
+
v-show="showLeft"
|
|
14
|
+
side="left"
|
|
15
|
+
@start="startScroll(-1)"
|
|
16
|
+
@end="stopScroll"
|
|
17
|
+
/>
|
|
11
18
|
<div
|
|
12
19
|
id="bk-blokkli-item-actions-controls"
|
|
13
|
-
ref="
|
|
14
|
-
class="bk-blokkli-item-actions-controls _bk_flex _bk_items-stretch _bk_whitespace-nowrap _bk_h-full _bk_flex-wrap _bk_lg:flex-nowrap _bk_bg-mono-950/90 _bk_scheme-dark _bk_relative _bk_z-50 _bk_lg:border _bk_lg:border-mono-400 _bk_lg:bg-mono-900"
|
|
20
|
+
ref="contentEl"
|
|
21
|
+
class="bk-blokkli-item-actions-controls _bk_flex _bk_items-stretch _bk_whitespace-nowrap _bk_h-full _bk_flex-wrap _bk_lg:flex-nowrap _bk_lg:w-max _bk_bg-mono-950/90 _bk_scheme-dark _bk_relative _bk_z-50 _bk_lg:border _bk_lg:border-mono-400 _bk_lg:bg-mono-900"
|
|
15
22
|
:class="{
|
|
16
23
|
'_bk_pointer-events-none': ui.isTransforming.value
|
|
17
24
|
}"
|
|
25
|
+
:style="{ '--bk-actions-scroll-x': `${-scrollX}px` }"
|
|
18
26
|
>
|
|
19
27
|
<Interactions />
|
|
20
28
|
<Title />
|
|
@@ -25,6 +33,12 @@
|
|
|
25
33
|
class="_bk_relative _bk_flex _bk_flex-1 _bk_lg:flex-initial _bk_lg:border-l _bk_lg:border-l-mono-500 _bk_justify-end"
|
|
26
34
|
/>
|
|
27
35
|
</div>
|
|
36
|
+
<ScrollArrow
|
|
37
|
+
v-show="showRight"
|
|
38
|
+
side="right"
|
|
39
|
+
@start="startScroll(1)"
|
|
40
|
+
@end="stopScroll"
|
|
41
|
+
/>
|
|
28
42
|
</div>
|
|
29
43
|
</template>
|
|
30
44
|
|
|
@@ -32,16 +46,32 @@
|
|
|
32
46
|
import { computed, useBlokkli, useTemplateRef, onBeforeUnmount } from "#imports";
|
|
33
47
|
import Interactions from "./Interactions/index.vue";
|
|
34
48
|
import Title from "./Title/index.vue";
|
|
35
|
-
import
|
|
49
|
+
import ScrollArrow from "./ScrollArrow/index.vue";
|
|
50
|
+
import { onBlokkliEvent, useStickyToolbar } from "#blokkli/editor/composables";
|
|
51
|
+
import { useToolbarScroll } from "./useToolbarScroll";
|
|
36
52
|
const { selection, ui } = useBlokkli();
|
|
37
53
|
const ACTIONS_HEIGHT = 52;
|
|
38
54
|
const el = useTemplateRef("el");
|
|
55
|
+
const contentEl = useTemplateRef("contentEl");
|
|
56
|
+
const {
|
|
57
|
+
scrollX,
|
|
58
|
+
showLeft,
|
|
59
|
+
showRight,
|
|
60
|
+
startScroll,
|
|
61
|
+
stopScroll,
|
|
62
|
+
scrollIntoView
|
|
63
|
+
} = useToolbarScroll({
|
|
64
|
+
viewportEl: el,
|
|
65
|
+
contentEl
|
|
66
|
+
});
|
|
67
|
+
onBlokkliEvent("actions:scrollIntoView", (e) => {
|
|
68
|
+
scrollIntoView(e.element);
|
|
69
|
+
});
|
|
39
70
|
useStickyToolbar(el, {
|
|
40
71
|
getPlacementY: () => "top",
|
|
41
72
|
shouldUpdate: () => !ui.actionsToolbarLocked.value && isVisible.value,
|
|
42
73
|
getHeight: () => ACTIONS_HEIGHT,
|
|
43
|
-
getMargin: () => 30
|
|
44
|
-
allowHorizontalOverflow: true
|
|
74
|
+
getMargin: () => 30
|
|
45
75
|
});
|
|
46
76
|
let mouseLeaveTimeout = null;
|
|
47
77
|
function onMouseLeave() {
|
|
@@ -67,6 +97,9 @@ onBeforeUnmount(() => {
|
|
|
67
97
|
const hasAnythingSelected = computed(
|
|
68
98
|
() => selection.hasHostSelected.value || !!selection.items.value.length
|
|
69
99
|
);
|
|
100
|
+
const paddedViewportWidth = computed(
|
|
101
|
+
() => Math.max(120, Math.round(ui.visibleViewportPadded.value.width))
|
|
102
|
+
);
|
|
70
103
|
const isVisible = computed(() => {
|
|
71
104
|
return !selection.isDragging.value && !selection.activeFieldLabel.value && !ui.isAnimating.value && !ui.hasTransformOverlayOpen.value && hasAnythingSelected.value && !ui.hasTooltipOpen.value && !ui.isApproving.value;
|
|
72
105
|
});
|
|
@@ -80,7 +113,6 @@ export default {
|
|
|
80
113
|
|
|
81
114
|
<style>/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
82
115
|
.bk.bk-blokkli-item-actions-inner {
|
|
83
|
-
transform: translate3d(0, 0, 0);
|
|
84
116
|
backface-visibility: hidden;
|
|
85
117
|
bottom: var(--bk-root-offset-bottom);
|
|
86
118
|
}
|
|
@@ -89,6 +121,14 @@ export default {
|
|
|
89
121
|
top: 0px !important;
|
|
90
122
|
width: auto !important;
|
|
91
123
|
bottom: initial !important;
|
|
124
|
+
max-width: var(--bk-actions-max-width, calc(100vw - 60px));
|
|
125
|
+
clip-path: inset(-100vh 0 -100vh 0);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
@media (width >= 64rem) {
|
|
129
|
+
.bk .bk-blokkli-item-actions-controls {
|
|
130
|
+
transform: translate3d(var(--bk-actions-scroll-x, 0px), 0, 0);
|
|
131
|
+
will-change: transform;
|
|
92
132
|
}
|
|
93
133
|
}
|
|
94
134
|
.bk-is-locked:is(.bk .bk-blokkli-item-actions-controls) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Ref } from 'vue';
|
|
2
|
+
export type UseToolbarScrollOptions = {
|
|
3
|
+
viewportEl: Readonly<Ref<HTMLElement | null>>;
|
|
4
|
+
contentEl: Readonly<Ref<HTMLElement | null>>;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Drives horizontal scroll of the actions toolbar's inner content via a
|
|
8
|
+
* transform translate, exposing arrow visibility flags and press-and-hold
|
|
9
|
+
* scroll controls.
|
|
10
|
+
*
|
|
11
|
+
* The viewport caps at the editor's safe area on desktop; when the content
|
|
12
|
+
* (icons, options, action buttons) is wider, the user scrolls by pressing
|
|
13
|
+
* and holding the arrow buttons rendered on the viewport edges. The
|
|
14
|
+
* underlying transform is applied without a CSS transition so selection
|
|
15
|
+
* changes don't animate back to zero. Mobile is unaffected — the options
|
|
16
|
+
* strip keeps its own native horizontal overflow there.
|
|
17
|
+
*/
|
|
18
|
+
export declare function useToolbarScroll(options: UseToolbarScrollOptions): {
|
|
19
|
+
scrollX: any;
|
|
20
|
+
showLeft: any;
|
|
21
|
+
showRight: any;
|
|
22
|
+
startScroll: (direction: -1 | 1) => void;
|
|
23
|
+
stopScroll: () => void;
|
|
24
|
+
scrollIntoView: (element: HTMLElement) => void;
|
|
25
|
+
};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { ref, computed, onBeforeUnmount } from "#imports";
|
|
2
|
+
import { onElementResize } from "#blokkli/editor/composables";
|
|
3
|
+
const LG_MEDIA_QUERY = "(min-width: 1024px)";
|
|
4
|
+
const SCROLL_SPEED_PX_PER_SEC = 1400;
|
|
5
|
+
const ARROW_OVERLAP_PX = 60;
|
|
6
|
+
export function useToolbarScroll(options) {
|
|
7
|
+
const scrollX = ref(0);
|
|
8
|
+
const viewportWidth = ref(0);
|
|
9
|
+
const contentWidth = ref(0);
|
|
10
|
+
const isLg = ref(
|
|
11
|
+
typeof window !== "undefined" ? window.matchMedia(LG_MEDIA_QUERY).matches : false
|
|
12
|
+
);
|
|
13
|
+
const maxScroll = computed(() => {
|
|
14
|
+
if (!isLg.value) {
|
|
15
|
+
return 0;
|
|
16
|
+
}
|
|
17
|
+
return Math.max(0, contentWidth.value - viewportWidth.value);
|
|
18
|
+
});
|
|
19
|
+
const showLeft = computed(() => maxScroll.value > 0 && scrollX.value > 0);
|
|
20
|
+
const showRight = computed(
|
|
21
|
+
() => maxScroll.value > 0 && scrollX.value < maxScroll.value
|
|
22
|
+
);
|
|
23
|
+
function clamp() {
|
|
24
|
+
if (scrollX.value > maxScroll.value) {
|
|
25
|
+
scrollX.value = maxScroll.value;
|
|
26
|
+
} else if (scrollX.value < 0) {
|
|
27
|
+
scrollX.value = 0;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
let rafId = null;
|
|
31
|
+
let lastTime = null;
|
|
32
|
+
let currentDirection = 0;
|
|
33
|
+
function tick(now) {
|
|
34
|
+
if (lastTime === null) {
|
|
35
|
+
lastTime = now;
|
|
36
|
+
}
|
|
37
|
+
const dt = (now - lastTime) / 1e3;
|
|
38
|
+
lastTime = now;
|
|
39
|
+
const next = Math.max(
|
|
40
|
+
0,
|
|
41
|
+
Math.min(
|
|
42
|
+
maxScroll.value,
|
|
43
|
+
scrollX.value + currentDirection * SCROLL_SPEED_PX_PER_SEC * dt
|
|
44
|
+
)
|
|
45
|
+
);
|
|
46
|
+
scrollX.value = next;
|
|
47
|
+
if (currentDirection < 0 && next === 0 || currentDirection > 0 && next >= maxScroll.value) {
|
|
48
|
+
stopScroll();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
rafId = window.requestAnimationFrame(tick);
|
|
52
|
+
}
|
|
53
|
+
function startScroll(direction) {
|
|
54
|
+
if (rafId !== null) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
currentDirection = direction;
|
|
58
|
+
lastTime = null;
|
|
59
|
+
rafId = window.requestAnimationFrame(tick);
|
|
60
|
+
}
|
|
61
|
+
function stopScroll() {
|
|
62
|
+
if (rafId !== null) {
|
|
63
|
+
window.cancelAnimationFrame(rafId);
|
|
64
|
+
rafId = null;
|
|
65
|
+
}
|
|
66
|
+
lastTime = null;
|
|
67
|
+
currentDirection = 0;
|
|
68
|
+
}
|
|
69
|
+
function scrollIntoView(element) {
|
|
70
|
+
const viewport = options.viewportEl.value;
|
|
71
|
+
if (!viewport || !isLg.value || maxScroll.value <= 0) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (!viewport.contains(element)) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const viewportRect = viewport.getBoundingClientRect();
|
|
78
|
+
const elRect = element.getBoundingClientRect();
|
|
79
|
+
const leftOverflow = viewportRect.left + ARROW_OVERLAP_PX - elRect.left;
|
|
80
|
+
const rightOverflow = elRect.right - (viewportRect.right - ARROW_OVERLAP_PX);
|
|
81
|
+
let next = scrollX.value;
|
|
82
|
+
if (leftOverflow > 0) {
|
|
83
|
+
next -= leftOverflow;
|
|
84
|
+
} else if (rightOverflow > 0) {
|
|
85
|
+
next += rightOverflow;
|
|
86
|
+
} else {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
scrollX.value = Math.max(0, Math.min(maxScroll.value, next));
|
|
90
|
+
}
|
|
91
|
+
onElementResize(options.viewportEl, (size) => {
|
|
92
|
+
viewportWidth.value = size.width;
|
|
93
|
+
clamp();
|
|
94
|
+
});
|
|
95
|
+
onElementResize(options.contentEl, (size) => {
|
|
96
|
+
contentWidth.value = size.width;
|
|
97
|
+
clamp();
|
|
98
|
+
});
|
|
99
|
+
let mql = null;
|
|
100
|
+
function onMediaChange(e) {
|
|
101
|
+
isLg.value = e.matches;
|
|
102
|
+
if (!e.matches) {
|
|
103
|
+
scrollX.value = 0;
|
|
104
|
+
stopScroll();
|
|
105
|
+
} else {
|
|
106
|
+
clamp();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (typeof window !== "undefined") {
|
|
110
|
+
mql = window.matchMedia(LG_MEDIA_QUERY);
|
|
111
|
+
mql.addEventListener("change", onMediaChange);
|
|
112
|
+
}
|
|
113
|
+
onBeforeUnmount(() => {
|
|
114
|
+
mql?.removeEventListener("change", onMediaChange);
|
|
115
|
+
stopScroll();
|
|
116
|
+
});
|
|
117
|
+
return {
|
|
118
|
+
scrollX,
|
|
119
|
+
showLeft,
|
|
120
|
+
showRight,
|
|
121
|
+
startScroll,
|
|
122
|
+
stopScroll,
|
|
123
|
+
scrollIntoView
|
|
124
|
+
};
|
|
125
|
+
}
|