@dou-ui/dashboard 0.1.0-alpha.3 → 0.1.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/core/document.js +10 -1
  2. package/dist/core/document.js.map +1 -1
  3. package/dist/core/history.js +23 -0
  4. package/dist/core/history.js.map +1 -1
  5. package/dist/core/transaction.js +8 -2
  6. package/dist/core/transaction.js.map +1 -1
  7. package/dist/dashboard/comment-button.js +6 -0
  8. package/dist/dashboard/comment-button.js.map +1 -0
  9. package/dist/dashboard/comment-button.vue_vue_type_script_setup_true_lang.js +59 -0
  10. package/dist/dashboard/comment-button.vue_vue_type_script_setup_true_lang.js.map +1 -0
  11. package/dist/dashboard/comment-card.js +6 -0
  12. package/dist/dashboard/comment-card.js.map +1 -0
  13. package/dist/dashboard/comment-card.vue_vue_type_script_setup_true_lang.js +128 -0
  14. package/dist/dashboard/comment-card.vue_vue_type_script_setup_true_lang.js.map +1 -0
  15. package/dist/dashboard/comments.js +144 -0
  16. package/dist/dashboard/comments.js.map +1 -0
  17. package/dist/dashboard/dashboard.js.map +1 -1
  18. package/dist/dashboard/dashboard.vue_vue_type_script_setup_true_lang.js +107 -18
  19. package/dist/dashboard/dashboard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  20. package/dist/dashboard/frame-context.js.map +1 -1
  21. package/dist/dashboard/widget-frame.js.map +1 -1
  22. package/dist/dashboard/widget-frame.vue_vue_type_script_setup_true_lang.js +10 -0
  23. package/dist/dashboard/widget-frame.vue_vue_type_script_setup_true_lang.js.map +1 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/locale.js +6 -0
  26. package/dist/locale.js.map +1 -1
  27. package/dist/style.css +1 -1
  28. package/dist/style.js +2 -3
  29. package/dist/types/core/document.d.ts +3 -2
  30. package/dist/types/core/history.d.ts +7 -1
  31. package/dist/types/core/transaction.d.ts +10 -1
  32. package/dist/types/core/types.d.ts +5 -0
  33. package/dist/types/dashboard/comment-button.vue.d.ts +15 -0
  34. package/dist/types/dashboard/comment-card.vue.d.ts +13 -0
  35. package/dist/types/dashboard/comments.d.ts +44 -0
  36. package/dist/types/dashboard/dashboard.vue.d.ts +10 -0
  37. package/dist/types/dashboard/frame-context.d.ts +2 -0
  38. package/dist/types/dashboard/types.d.ts +30 -0
  39. package/dist/types/index.d.ts +20 -1
  40. package/dist/types/locale.d.ts +4 -0
  41. package/package.json +8 -8
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_normalizeClass","_unref","_createVNode","GridLayout","_normalizeStyle","_withCtx","WidgetFrame","_createCommentVNode","_createElementVNode","_toDisplayString","_createBlock","WidgetSettings","WidgetBody"],"sources":["../../src/dashboard/dashboard.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { LayoutGridPlusIcon, fileIconOf } from '@dou-ui/icons'\nimport type { SheetExporter, SheetWorkbook } from '@dou-ui/sheet/core'\nimport {\n DouDialog,\n DouDrawer,\n DouEmpty,\n DouInput,\n downloadBlob,\n matchesHotkey,\n useLocale,\n} from 'dou-ui'\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n provide,\n ref,\n shallowReactive,\n shallowRef,\n toRaw,\n watch,\n} from 'vue'\nimport { emptyDocument } from '../core/document'\nimport { DashboardHistory } from '../core/history'\nimport {\n applySteps,\n cloneJson,\n DashboardTransaction,\n replaceWidgets,\n sameValue,\n} from '../core/transaction'\nimport type { DashboardStep, DashboardTransactionMeta } from '../core/transaction'\nimport type { DashboardDocument, DashboardPlace, DashboardWidget } from '../core/types'\nimport type {\n DashboardPeer,\n DashboardPresence,\n DashboardPresenceAction,\n} from '../core/collaboration'\nimport { dataContextKey } from '../data/context'\nimport { filterText, isEmptyFilter } from '../data/filters'\nimport { createSourceStore, sameSource } from '../data/store'\nimport type {\n DashboardFilters,\n DashboardLinkedFilter,\n DashboardSetFilterOptions,\n} from '../data/types'\nimport GridLayout from '../grid/grid-layout.vue'\nimport { DEFAULT_BREAKPOINTS, DEFAULT_COLUMNS, gridTiers } from '../grid/tiers'\nimport type { GridDragEvent, GridDropEvent, GridLayoutExpose, GridLayouts } from '../grid/types'\nimport { findPlace, fitItem, moveItem } from '../layout/engine'\nimport type { GridItem, GridLayoutOptions } from '../layout/types'\nimport { format, useDashboardMessages } from '../locale'\nimport { DEFAULT_WIDGET_SIZE, defaultPropsOf } from '../widget/define'\nimport type { DashboardWidgetType } from '../widget/define'\nimport type {\n DashboardAddOptions,\n DashboardEmits,\n DashboardExportErrorEvent,\n DashboardExportOptions,\n DashboardExpose,\n DashboardSaveOptions,\n DashboardProps,\n} from './types'\nimport { createObservers, observersKey } from './observers'\nimport { elementToPNG } from './export'\nimport type { DashboardImageOptions } from './export'\nimport WidgetBody from './widget-body.vue'\nimport WidgetFrame from './widget-frame.vue'\nimport WidgetSettings from './widget-settings.vue'\nimport { frameContextKey } from './frame-context'\nimport type { FrameExporter, WidgetAction } from './frame-context'\n\ndefineOptions({ name: 'DouDashboard' })\n\nconst props = withDefaults(defineProps<Omit<DashboardProps, 'modelValue' | 'filters'>>(), {\n widgets: () => [],\n columns: () => DEFAULT_COLUMNS,\n breakpoints: () => DEFAULT_BREAKPOINTS,\n rowHeight: 80,\n gap: 16,\n compact: 'vertical',\n})\nconst emit = defineEmits<Omit<DashboardEmits, 'update:modelValue' | 'update:filters'>>()\nconst model = defineModel<DashboardDocument>({ default: emptyDocument })\nconst filters = defineModel<DashboardFilters>('filters', { default: () => ({}) })\nconst messages = useDashboardMessages(() => props.messages)\n\nconst grid = ref<GridLayoutExpose>()\nconst observers = createObservers()\nprovide(observersKey, observers)\nonBeforeUnmount(() => observers.dispose())\n/** This many widgets are drawn in full at once, the rest when they come near the view. */\nconst EAGER = 16\nconst root = ref<HTMLElement>()\n\nconst typeMap = computed(() => new Map(props.widgets.map((type) => [type.type, type])))\nconst typeOf = (widget: DashboardWidget) => typeMap.value.get(widget.type)\nconst widgetMap = computed(() => new Map(model.value.widgets.map((widget) => [widget.id, widget])))\n/** The first widgets of the document, drawn in full without waiting to be seen. */\nconst eagerIds = computed(() => new Set(model.value.widgets.slice(0, EAGER).map((w) => w.id)))\n/** Widgets added once the dashboard is up are drawn in full straight away (not reactive on purpose). */\nlet mounted = false\nonMounted(() => (mounted = true))\nconst isEager = (id: string) => mounted || eagerIds.value.has(id)\nconst titleOf = (widget: DashboardWidget) => widget.title || typeOf(widget)?.label || widget.type\n\nconst tiers = computed(() => gridTiers(props.columns, props.breakpoints))\n/** The widest breakpoint: its places are the main ones. */\nconst main = computed(() => tiers.value[0]!)\nconst mainOptions = computed<GridLayoutOptions>(() => ({\n columns: Math.max(1, Math.round(main.value.columns)),\n compact: props.compact,\n}))\n\n// ---------------------------------------------------------------------------\n// Changes and history\n\nconst history = new DashboardHistory()\n/** Bumped whenever the history changes, so `canUndo` and `canRedo` update. */\nconst historyVersion = ref(0)\n/** The document last emitted, to tell our own changes from the app's. */\nlet emitted: DashboardDocument | undefined\nwatch(model, (doc) => {\n // the app may hand back a reactive copy of what was emitted\n // a document the app put in itself: the old steps no longer fit it\n if (toRaw(doc) === emitted) return\n history.clear()\n historyVersion.value++\n})\n\nfunction commit(tr: DashboardTransaction) {\n emitted = toRaw(tr.doc)\n model.value = tr.doc\n emit('change', tr)\n}\n\n/** A transaction on the document as it is now, to `dispatch`. */\nfunction transaction() {\n return new DashboardTransaction(model.value)\n}\n\n/** Makes the changes of a transaction, as one undo step (or part of one, by `meta.group`). */\nfunction dispatch(tr: DashboardTransaction) {\n if (toRaw(tr.before) !== toRaw(model.value))\n throw new Error(\n '[@dou-ui/dashboard] the transaction was made on another version of the dashboard',\n )\n if (!tr.changed) return\n const shared = props.collaboration\n if (!shared) {\n history.record(tr)\n historyVersion.value++\n }\n commit(tr)\n shared?.transaction(tr)\n}\n\n/** Steps made into a transaction and dispatched, for the dashboard's own changes. */\nfunction run(steps: DashboardStep[], meta: DashboardTransactionMeta) {\n const tr = applySteps(model.value, steps, meta)\n dispatch(tr)\n return tr\n}\n\nfunction undo() {\n if (props.collaboration) return props.collaboration.undo()\n const tr = history.undo(model.value)\n historyVersion.value++\n if (!tr) return false\n if (tr.changed) commit(tr)\n return true\n}\n\nfunction redo() {\n if (props.collaboration) return props.collaboration.redo()\n const tr = history.redo(model.value)\n historyVersion.value++\n if (!tr) return false\n if (tr.changed) commit(tr)\n return true\n}\n\nconst canUndo = computed(() =>\n props.collaboration ? props.collaboration.canUndo() : (historyVersion.value, history.canUndo),\n)\nconst canRedo = computed(() =>\n props.collaboration ? props.collaboration.canRedo() : (historyVersion.value, history.canRedo),\n)\n\n// ---------------------------------------------------------------------------\n// The grid: widgets as items, places by breakpoint\n\nfunction limitsOf(type: DashboardWidgetType<any> | undefined) {\n const size = type?.size ?? DEFAULT_WIDGET_SIZE\n return {\n w: size.w,\n h: size.h,\n minW: size.minW,\n maxW: size.maxW,\n minH: size.minH,\n maxH: size.maxH,\n }\n}\n\n/** The widgets on the widest breakpoint; those without a place there get the first spot they fit. */\nconst placeOf = (item: DashboardPlace): DashboardPlace => ({\n x: item.x,\n y: item.y,\n w: item.w,\n h: item.h,\n})\n\n// The item of a widget that didn't change is the same object as before, so\n// the grid and its other items have nothing to draw again.\nlet itemCache = new WeakMap<DashboardWidget, GridItem>()\nwatch([typeMap, main], () => (itemCache = new WeakMap()), { flush: 'sync' })\nconst items = computed<GridItem[]>(() => {\n const name = main.value.name\n const options = mainOptions.value\n const placed: GridItem[] = []\n const result = new Map<string, GridItem>()\n const missing: DashboardWidget[] = []\n for (const widget of model.value.widgets) {\n const raw = toRaw(widget)\n const place = raw.place[name]\n if (!place) {\n missing.push(raw)\n continue\n }\n let item = itemCache.get(raw)\n if (!item) {\n const { minW, maxW, minH, maxH } = limitsOf(typeOf(raw))\n item = { id: raw.id, ...placeOf(place), minW, maxW, minH, maxH }\n itemCache.set(raw, item)\n }\n placed.push(item)\n result.set(raw.id, item)\n }\n for (const widget of missing) {\n const fitted = fitItem(\n { id: widget.id, x: 0, y: 0, ...limitsOf(typeOf(widget)) },\n options.columns,\n )\n const item = { ...fitted, ...findPlace(placed, fitted, options) }\n placed.push(item)\n result.set(widget.id, item)\n }\n return model.value.widgets.map((widget) => result.get(widget.id)!)\n})\n\n/** The places on the narrower breakpoints. */\nconst layouts = computed<GridLayouts>(() => {\n const result: GridLayouts = {}\n for (const tier of tiers.value.slice(1)) {\n const list = []\n for (const widget of model.value.widgets) {\n const place = widget.place[tier.name]\n if (place) list.push({ id: widget.id, ...place })\n }\n if (list.length) result[tier.name] = list\n }\n return result\n})\n\n// The grid tells a move with `update:modelValue`, `update:layouts` and\n// `drop` one after another; they are gathered into one change.\nlet pending: { items?: GridItem[]; layouts?: GridLayouts; drop?: { id: string; type: string } } = {}\nlet flushing = false\nfunction gather(part: typeof pending) {\n Object.assign(pending, part)\n if (flushing) return\n flushing = true\n queueMicrotask(flush)\n}\n\nfunction flush() {\n flushing = false\n const { items: list, layouts: saved, drop } = pending\n pending = {}\n const doc = model.value\n const places = new Map<string, DashboardWidget['place']>()\n const setPlace = (id: string, name: string, item: DashboardPlace) => {\n let place = places.get(id)\n if (!place) places.set(id, (place = { ...widgetMap.value.get(id)?.place }))\n place[name] = placeOf(item)\n }\n for (const item of list ?? []) setPlace(item.id, main.value.name, item)\n for (const [name, others] of Object.entries(saved ?? {}))\n for (const item of others ?? []) setPlace(item.id, name, item)\n const steps: DashboardStep[] = []\n for (const [id, place] of places) {\n if (widgetMap.value.has(id)) {\n steps.push({ type: 'update', id, patch: { place } })\n } else if (drop?.id === id) {\n const type = typeMap.value.get(drop.type)\n if (type)\n steps.push({ type: 'add', widget: newWidget(id, type, place), index: doc.widgets.length })\n }\n }\n const tr = run(steps, { origin: drop ? 'drop' : 'layout' })\n if (drop && tr.changed) {\n const widget = widgetMap.value.get(drop.id)\n if (widget) say(format(messages.value.added, { item: titleOf(widget) }))\n }\n}\n\nfunction onDrop(event: GridDropEvent) {\n const data = event.data as { type?: string } | undefined\n if (data?.type) gather({ drop: { id: event.item.id, type: data.type } })\n}\n\nconst dragging = ref(false)\n\n// ---------------------------------------------------------------------------\n// Adding, copying and removing\n\nfunction newId(type: string) {\n const used = widgetMap.value\n for (;;) {\n const id = props.createId?.(type) ?? `${type}-${Math.random().toString(36).slice(2, 8)}`\n if (!used.has(id)) return id\n if (props.createId)\n throw new Error(`[@dou-ui/dashboard] createId gave \"${id}\", which is already in use`)\n }\n}\n\nfunction newWidget(\n id: string,\n type: DashboardWidgetType<any>,\n place: DashboardWidget['place'],\n options: Pick<DashboardAddOptions, 'title' | 'props'> = {},\n): DashboardWidget {\n const widget: DashboardWidget = { id, type: type.type, place }\n if (options.title) widget.title = options.title\n const initial = defaultPropsOf(type)\n if (initial || options.props) widget.props = { ...initial, ...options.props }\n return widget\n}\n\n/**\n * Puts a new item on the widest breakpoint, at `at` (pushing the others\n * away) or in the first spot it fits; the steps also move any widget it\n * pushed.\n */\nfunction placeNew(item: GridItem, at: Pick<DashboardPlace, 'x' | 'y'> | undefined) {\n const options = mainOptions.value\n const fitted = fitItem(item, options.columns)\n const spot = at ?? findPlace(items.value, fitted, options)\n const layout = moveItem([...items.value, { ...fitted, ...spot }], item.id, spot, options)\n const steps: DashboardStep[] = []\n let place: DashboardPlace = { ...fitted, ...spot }\n for (const next of layout) {\n if (next.id === item.id) {\n place = placeOf(next)\n continue\n }\n const widget = widgetMap.value.get(next.id)\n const old = widget && items.value.find((other) => other.id === next.id)\n if (widget && old && (old.x !== next.x || old.y !== next.y))\n steps.push({\n type: 'update',\n id: next.id,\n patch: { place: { ...widget.place, [main.value.name]: placeOf(next) } },\n })\n }\n return { place, steps }\n}\n\nfunction addWidget(typeName: string, options: DashboardAddOptions = {}) {\n const type = typeMap.value.get(typeName)\n if (!type) return undefined\n const id = newId(typeName)\n const { place, steps } = placeNew({ id, x: 0, y: 0, ...limitsOf(type) }, options.at)\n const widget = newWidget(id, type, { [main.value.name]: place }, options)\n run([{ type: 'add', widget, index: model.value.widgets.length }, ...steps], {\n origin: 'api',\n })\n say(format(messages.value.added, { item: titleOf(widget) }))\n if (options.focus !== false) void nextTick(() => focusWidget(id))\n return id\n}\n\n/** Adds a copy of a widget (from this dashboard or the clipboard) beside `near`, or in the first free spot. */\nfunction addCopy(source: DashboardWidget, near?: GridItem) {\n const type = typeOf(source)\n const id = newId(source.type)\n const columns = mainOptions.value.columns\n const size = near ?? { ...limitsOf(type), ...source.place[main.value.name] }\n const at = near\n ? near.x + near.w * 2 <= columns\n ? { x: near.x + near.w, y: near.y }\n : { x: near.x, y: near.y + near.h }\n : undefined\n const { place, steps } = placeNew({ ...limitsOf(type), id, x: 0, y: 0, w: size.w, h: size.h }, at)\n const widget: DashboardWidget = {\n ...cloneJson(source),\n id,\n place: { [main.value.name]: place },\n }\n const index = near\n ? model.value.widgets.findIndex((other) => other.id === near.id) + 1\n : model.value.widgets.length\n run([{ type: 'add', widget, index }, ...steps], { origin: 'copy' })\n say(format(messages.value.added, { item: titleOf(widget) }))\n void nextTick(() => focusWidget(id))\n return id\n}\n\nfunction duplicateWidget(id: string) {\n const widget = widgetMap.value.get(id)\n const item = items.value.find((other) => other.id === id)\n return widget && item ? addCopy(widget, item) : undefined\n}\n\nfunction removeWidget(id: string) {\n const list = model.value.widgets\n const index = list.findIndex((widget) => widget.id === id)\n if (index < 0) return\n const widget = list[index]!\n const hadFocus = root.value?.contains(document.activeElement)\n const neighbour = list[index + 1] ?? list[index - 1]\n if (settingsId.value === id) settingsId.value = undefined\n if (fullscreenId.value === id) fullscreenId.value = undefined\n run([{ type: 'remove', id }], { origin: 'api' })\n say(format(messages.value.removed, { item: titleOf(widget) }))\n if (hadFocus) void nextTick(() => (neighbour ? focusWidget(neighbour.id) : root.value?.focus()))\n}\n\nfunction focusWidget(id: string) {\n grid.value?.focusItem(id)\n}\n\n/** The widget being dragged in, which has no widget yet: its name is its type's. */\nlet adding: { id: string; label: string } | undefined\n\nfunction startAdd(event: PointerEvent, typeName: string) {\n const type = typeMap.value.get(typeName)\n if (!type || !props.editable) return\n adding = { id: newId(typeName), label: type.label }\n grid.value?.startDrop(event, { id: adding.id, ...limitsOf(type) }, { type: typeName })\n}\n\nfunction labelOf(item: GridItem) {\n const widget = widgetMap.value.get(item.id)\n return widget ? titleOf(widget) : item.id === adding?.id ? adding.label : item.id\n}\n\nfunction setProps(id: string, patch: Record<string, unknown>, options: { group?: string } = {}) {\n const widget = widgetMap.value.get(id)\n if (!widget) return\n run([{ type: 'update', id, patch: { props: { ...widget.props, ...patch } } }], {\n origin: 'widget',\n group: options.group,\n })\n}\n\nfunction rename(id: string, title: string) {\n run([{ type: 'update', id, patch: { title: title.trim() || undefined } }], {\n origin: 'title',\n })\n}\n\n// ---------------------------------------------------------------------------\n// Settings and full screen\n\nconst settingsId = ref<string>()\nconst settingsWidget = computed(() =>\n settingsId.value ? widgetMap.value.get(settingsId.value) : undefined,\n)\nconst fullscreenId = ref<string>()\nconst fullscreenWidget = computed(() =>\n fullscreenId.value ? widgetMap.value.get(fullscreenId.value) : undefined,\n)\n/** The widget to give focus back to when a drawer or dialog closes. */\nlet returnTo: string | undefined\n\nfunction openSettings(id: string) {\n if (!props.editable || !widgetMap.value.has(id)) return\n returnTo = id\n settingsId.value = id\n}\n\nfunction openFullscreen(id: string) {\n const widget = widgetMap.value.get(id)\n if (!widget || typeOf(widget)?.fullscreen === false) return\n returnTo = id\n fullscreenId.value = id\n}\n\nfunction restoreFocus() {\n const id = returnTo\n returnTo = undefined\n if (id && widgetMap.value.has(id)) focusWidget(id)\n}\n\nwatch(\n () => props.editable,\n (editable) => {\n if (!editable) settingsId.value = undefined\n },\n)\n\nfunction onAction(id: string, action: WidgetAction) {\n if (action === 'settings') openSettings(id)\n else if (action === 'fullscreen') openFullscreen(id)\n else if (action === 'duplicate') duplicateWidget(id)\n else removeWidget(id)\n}\n\n// ---------------------------------------------------------------------------\n// Editing together\n\n/** Changes from others wait while a widget is dragged here; then the shared document is read again. */\nlet held = false\n\nfunction applyShared(doc: DashboardDocument, origin: 'remote' | 'undo' | 'redo') {\n if (dragging.value) {\n held = true\n return\n }\n const tr = replaceWidgets(new DashboardTransaction(model.value), doc)\n if (!tr.changed) return\n tr.setMeta('history', false).setMeta('origin', origin)\n const ids = new Set(tr.doc.widgets.map((widget) => widget.id))\n if (settingsId.value && !ids.has(settingsId.value)) settingsId.value = undefined\n if (fullscreenId.value && !ids.has(fullscreenId.value)) fullscreenId.value = undefined\n commit(tr)\n}\n\n// one written in the template is new on every render: each one starts over and clears undo\nlet setupTimes: number[] = []\nlet setupWarned = false\nfunction warnRepeatedSetup() {\n if (process.env.NODE_ENV === 'production' || setupWarned) return\n const now = Date.now()\n setupTimes = [...setupTimes.filter((time) => now - time < 1000), now]\n if (setupTimes.length < 4) return\n setupWarned = true\n console.warn(\n '[@dou-ui/dashboard] collaboration keeps being replaced, which starts it over and clears undo each time. Create it once in <script setup> instead of in the template.',\n )\n}\n\nwatch(\n () => props.collaboration,\n (shared, _, onCleanup) => {\n if (shared) warnRepeatedSetup()\n history.clear()\n historyVersion.value++\n if (!shared) return\n const stop = shared.setup({ document: () => model.value, apply: applyShared })\n onCleanup(() => {\n shared.presence?.(null)\n stop()\n })\n },\n { immediate: true },\n)\n\n/** The widget being moved or resized here, and how. */\nconst drag = shallowRef<GridDragEvent>()\nfunction onDragStart(event: GridDragEvent) {\n dragging.value = true\n drag.value = event\n}\nfunction onDragEnd() {\n dragging.value = false\n drag.value = undefined\n if (!held) return\n held = false\n // after the drop's own change, which the grid hands over in a microtask\n queueMicrotask(() => queueMicrotask(() => props.collaboration?.sync()))\n}\n\n/** The widget whose item, or a control in it, has focus. */\nconst focused = ref<string>()\nfunction onFocusIn(event: FocusEvent) {\n const item = (event.target as HTMLElement).closest?.<HTMLElement>('[data-grid-id]')\n focused.value = item?.closest('.dou-dashboard') === root.value ? item?.dataset.gridId : undefined\n}\nfunction onFocusOut(event: FocusEvent) {\n if (!root.value?.contains(event.relatedTarget as Node | null)) focused.value = undefined\n}\n\n/** What this person is doing, shown to the others. */\nconst presence = computed<DashboardPresence | null>(() => {\n const moving = drag.value\n if (moving && moving.kind !== 'drop' && widgetMap.value.has(moving.id))\n return { widget: moving.id, action: moving.kind as DashboardPresenceAction }\n if (settingsId.value) return { widget: settingsId.value, action: 'settings' }\n if (focused.value && widgetMap.value.has(focused.value))\n return { widget: focused.value, action: 'focus' }\n return null\n})\nwatch(\n [presence, () => props.collaboration] as const,\n ([current, shared], previous) => {\n if (!shared?.presence) return\n const [before, sharedBefore] = previous ?? []\n if (\n sharedBefore === shared &&\n before?.widget === current?.widget &&\n before?.action === current?.action\n )\n return\n shared.presence(current)\n },\n { immediate: true },\n)\nconst NO_PEERS: readonly DashboardPeer[] = []\n\nprovide(frameContextKey, {\n widget: (id) => widgetMap.value.get(id),\n type: typeOf,\n title: titleOf,\n editing: () => props.editable,\n messages: () => messages.value,\n eager: isEager,\n all: () => showAll.value,\n setProps,\n action: onAction,\n rename,\n linked: (id) => linksByWidget.value.get(id) ?? NO_LINKS,\n clearFilter: (key) => setFilter(undefined, key, undefined),\n peers: (id) => props.collaboration?.peers?.(id) ?? NO_PEERS,\n setWorkbook,\n exporters: (id) => (workbooks.has(id) ? exporterList.value : NO_EXPORTERS),\n exportTo: exportFromMenu,\n exporting: (id) => exporting.has(id),\n setDrawn: (id, drawn) => (drawn ? drawnIds.add(id) : drawnIds.delete(id)),\n exportError: (id) => exportErrors.get(id),\n clearExportError: (id) => exportErrors.delete(id),\n})\n\n// ---------------------------------------------------------------------------\n// Exporting a widget's content as a file\n\n/** How each mounted widget gives its content as a workbook; see `setWorkbook`. */\nconst workbooks = shallowReactive(new Map<string, () => SheetWorkbook | undefined>())\nfunction setWorkbook(id: string, get: () => SheetWorkbook | undefined) {\n workbooks.set(id, get)\n return () => {\n if (workbooks.get(id) === get) workbooks.delete(id)\n }\n}\n\n// the file code comes with the first exporter, in a chunk of its own\ntype SheetCore = typeof import('@dou-ui/sheet/core')\nconst sheetCore = shallowRef<SheetCore>()\nlet loadingCore: Promise<SheetCore> | undefined\nfunction loadSheetCore() {\n loadingCore ??= import('@dou-ui/sheet/core').then((core) => (sheetCore.value = core))\n return loadingCore\n}\nwatch(\n () => props.exporters?.length,\n (count) => count && void loadSheetCore(),\n { immediate: true },\n)\n\nconst NO_EXPORTERS: FrameExporter[] = []\nconst { locale } = useLocale()\n/** The exporters of the menu, without those that draw a sheet's grid. */\nconst exporterList = computed<FrameExporter[]>(() => {\n const core = sheetCore.value\n if (!core) return NO_EXPORTERS\n const sheetMessages = core.sheetMessagesFor(locale.value.name)\n return (props.exporters ?? [])\n .filter((exporter) => exporter.needs !== 'view')\n .map((exporter) => ({\n name: exporter.name,\n label: typeof exporter.label === 'function' ? exporter.label(sheetMessages) : exporter.label,\n icon: exporter.icon ?? fileIconOf(exporter.extension),\n }))\n})\n\nfunction exporterOf(exporter: string | SheetExporter) {\n if (typeof exporter !== 'string') return exporter\n const found = props.exporters?.find((item) => item.name === exporter)\n if (!found) throw new RangeError(`[@dou-ui/dashboard] there is no exporter \"${exporter}\"`)\n return found\n}\n\n/** A widget's file and sheet name: its title, or its type's name. */\nconst exportNameOf = (widget: DashboardWidget) => titleOf(widget).trim() || widget.type\n\n/** Why something failed, as people read it: a file error's `reason`, or its message. */\nfunction reasonOf(error: unknown) {\n if (error instanceof Error)\n return 'reason' in error && typeof error.reason === 'string' ? error.reason : error.message\n return String(error)\n}\n\n/**\n * A widget's content as a file: its workbook written by the exporter, a\n * name from `exporters` or an exporter itself. Waits for the data shown,\n * and draws the widget first when it is far from the view.\n */\nasync function exportWidget(\n id: string,\n exporter: string | SheetExporter,\n options: DashboardExportOptions = {},\n): Promise<Blob> {\n const chosen = exporterOf(exporter)\n const widget = widgetMap.value.get(id)\n if (!widget) throw new RangeError(`[@dou-ui/dashboard] there is no widget \"${id}\"`)\n const core = await loadSheetCore()\n // a widget drawn already that gives no workbook never will: no need to draw them all\n await settle(5000, !drawnIds.has(id))\n options.signal?.throwIfAborted()\n const get = workbooks.get(id)\n const book = get?.()\n if (!book)\n throw new core.SheetFileError(\n get\n ? `[@dou-ui/dashboard] the widget \"${id}\" has no data to export now`\n : `[@dou-ui/dashboard] the widget \"${id}\" doesn't give its content as a workbook (setWorkbook)`,\n 'empty',\n messages.value.nothingToExport,\n )\n // sheets without a name take the widget's, as the file does\n const name = exportNameOf(widget)\n const named = book.sheets.some((sheet) => !sheet.name)\n ? { ...book, sheets: book.sheets.map((sheet) => (sheet.name ? sheet : { ...sheet, name })) }\n : book\n return core.exportWorkbook(named, chosen, {\n options: options.options,\n signal: options.signal,\n locale: locale.value.name,\n })\n}\n\n/** The widgets drawn in full; the others show only their title until they come near. */\nconst drawnIds = new Set<string>()\n\n/** Why the last export from each widget's menu failed, shown over its content until closed. */\nconst exportErrors = shallowReactive(new Map<string, string>())\n/** The widgets exporting now, whose export button waits. */\nconst exporting = shallowReactive(new Set<string>())\n\n/**\n * Exports a widget's content and saves the file in the downloads, as its\n * menu does. A failure shows over the widget and comes as `exportError`,\n * and the promise rejects.\n */\nasync function saveWidget(\n id: string,\n exporter: string | SheetExporter,\n options: DashboardSaveOptions = {},\n): Promise<void> {\n const chosen = exporterOf(exporter)\n const widget = widgetMap.value.get(id)\n if (!widget) throw new RangeError(`[@dou-ui/dashboard] there is no widget \"${id}\"`)\n const name = options.fileName ?? `${exportNameOf(widget)}.${chosen.extension}`\n exportErrors.delete(id)\n exporting.add(id)\n let blob: Blob\n try {\n blob = await exportWidget(id, chosen, options)\n } catch (error) {\n const event: DashboardExportErrorEvent = {\n widget: id,\n exporter: chosen.name,\n error,\n message: format(messages.value.exportFailed, { name, reason: reasonOf(error) }),\n defaultPrevented: false,\n preventDefault() {\n this.defaultPrevented = true\n },\n }\n emit('exportError', event)\n // the notice is read out itself; told by the app, it is only read out\n if (event.defaultPrevented) say(event.message)\n else exportErrors.set(id, event.message)\n throw error\n } finally {\n exporting.delete(id)\n }\n downloadBlob(blob, name)\n say(format(messages.value.exported, { name }))\n}\n\nfunction exportFromMenu(id: string, name: string) {\n if (exporting.has(id)) return\n // the failure is shown over the widget\n saveWidget(id, name).catch(() => {})\n}\n\n// ---------------------------------------------------------------------------\n// Data and filters\n\nconst store = createSourceStore(() => props.sources)\nonBeforeUnmount(() => store.dispose())\n// a source replaced by one that loads differently loads again\nwatch(\n () => props.sources,\n (next, previous) => {\n const names = new Set([...Object.keys(previous ?? {}), ...Object.keys(next ?? {})])\n for (const name of names) if (!sameSource(previous?.[name], next?.[name])) store.reload(name)\n },\n)\n\n/** The filters set by widgets, by key: they apply to every widget but the one that set them. */\nconst links = shallowRef(new Map<string, DashboardLinkedFilter>())\nconst EMPTY_SET: ReadonlySet<string> = new Set()\nconst NO_LINKS: DashboardLinkedFilter[] = []\nconst linksByWidget = computed(() => {\n const result = new Map<string, DashboardLinkedFilter[]>()\n for (const link of links.value.values()) {\n const list = result.get(link.widget)\n if (list) list.push(link)\n else result.set(link.widget, [link])\n }\n return result\n})\nconst emittedByWidget = computed(() => {\n const result = new Map<string, Set<string>>()\n for (const [id, list] of linksByWidget.value)\n result.set(id, new Set(list.map((link) => link.key)))\n return result\n})\n\n// The values as set last: with `v-model:filters` the model only updates once\n// the parent draws again, so several filters set at once build on this.\nconst values = shallowRef<DashboardFilters>(filters.value)\nwatch(filters, (next) => (values.value = next))\n\nfunction setFilter(\n widget: string | undefined,\n key: string,\n value: unknown,\n options: DashboardSetFilterOptions = {},\n) {\n const next = { ...values.value }\n const nextLinks = new Map(links.value)\n if (isEmptyFilter(value)) delete next[key]\n else next[key] = value\n if (widget && !isEmptyFilter(value) && widgetMap.value.has(widget))\n nextLinks.set(key, { key, value, label: options.label ?? filterText(value), widget })\n else nextLinks.delete(key)\n links.value = nextLinks\n values.value = next\n filters.value = next\n}\n\nfunction clearFilters() {\n links.value = new Map()\n values.value = {}\n filters.value = {}\n}\n\n// a filter changed from outside (the filter bar, the app) is no longer the widget's\nwatch(filters, (current) => {\n let next: Map<string, DashboardLinkedFilter> | undefined\n for (const [key, link] of links.value) {\n if (sameValue(current[key], link.value)) continue\n next ??= new Map(links.value)\n next.delete(key)\n }\n if (next) links.value = next\n})\n\n// the filters of a widget that is removed go with it\nwatch(widgetMap, (map) => {\n for (const link of links.value.values())\n if (!map.has(link.widget)) setFilter(undefined, link.key, undefined)\n})\n\nconst sourceNames = computed(() => Object.keys(props.sources ?? {}))\nprovide(dataContextKey, {\n store,\n sourceNames: () => sourceNames.value,\n filters: () => values.value,\n emitted: (id) => emittedByWidget.value.get(id) ?? EMPTY_SET,\n linked: (id) => linksByWidget.value.get(id) ?? NO_LINKS,\n setFilter,\n})\n\n// ---------------------------------------------------------------------------\n// Keyboard and clipboard\n\nconst CLIPBOARD_KIND = 'dou-dashboard/widget'\n\nfunction isTyping(target: EventTarget | null) {\n const el = target as HTMLElement | null\n if (!el?.tagName) return false\n return (\n el.isContentEditable ||\n el.tagName === 'TEXTAREA' ||\n el.tagName === 'SELECT' ||\n (el.tagName === 'INPUT' &&\n !['checkbox', 'radio', 'button', 'range', 'color'].includes((el as HTMLInputElement).type))\n )\n}\n\n/** The widget whose item itself has focus (not a control inside it). */\nfunction focusedId(target: EventTarget | null) {\n const el = target as HTMLElement | null\n return el?.dataset?.gridId && el.closest('.dou-dashboard') === root.value\n ? el.dataset.gridId\n : undefined\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (!props.editable || event.defaultPrevented || isTyping(event.target)) return\n if (matchesHotkey(event, 'mod+z')) {\n event.preventDefault()\n undo()\n return\n }\n if (matchesHotkey(event, 'mod+shift+z') || matchesHotkey(event, 'mod+y')) {\n event.preventDefault()\n redo()\n return\n }\n const id = focusedId(event.target)\n if (!id || dragging.value) return\n if (event.key === 'Delete' || event.key === 'Backspace') {\n event.preventDefault()\n removeWidget(id)\n } else if (matchesHotkey(event, 'mod+d')) {\n event.preventDefault()\n duplicateWidget(id)\n }\n}\n\nfunction onCopy(event: ClipboardEvent, cut = false) {\n if (isTyping(event.target)) return\n const id = focusedId(event.target)\n const widget = id && widgetMap.value.get(id)\n if (!widget || !event.clipboardData) return\n event.clipboardData.setData('text/plain', JSON.stringify({ kind: CLIPBOARD_KIND, widget }))\n event.preventDefault()\n if (cut && props.editable) removeWidget(widget.id)\n}\n\nfunction onPaste(event: ClipboardEvent) {\n if (!props.editable || isTyping(event.target)) return\n let data: { kind?: string; widget?: DashboardWidget } | undefined\n try {\n data = JSON.parse(event.clipboardData?.getData('text/plain') ?? '')\n } catch {\n return\n }\n const widget = data?.kind === CLIPBOARD_KIND ? data.widget : undefined\n if (!widget?.type || !typeMap.value.has(widget.type)) return\n event.preventDefault()\n const id = focusedId(event.target)\n addCopy(widget, id ? items.value.find((item) => item.id === id) : undefined)\n}\n\n// ---------------------------------------------------------------------------\n// Export and print\n\n/** Every widget drawn in full, not only those near the view. */\nconst showAll = ref(false)\nconst nextFrame = () => new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))\n\n/** Draws every widget (unless `all` is false) and waits for their sources (at most `timeout` ms) and one more frame. */\nasync function settle(timeout = 5000, all = true) {\n if (all) showAll.value = true\n await nextTick()\n const start = performance.now()\n await nextFrame()\n while (store.busy() && performance.now() - start < timeout) await nextFrame()\n await nextFrame()\n await nextFrame()\n}\n\n/** The dashboard as it is shown, every widget drawn, as a PNG image. */\nasync function exportPNG(options?: DashboardImageOptions) {\n await settle()\n const el = root.value!\n // the controls are left out; the copy is made before the class goes\n el.classList.add('is-exporting')\n try {\n return elementToPNG(el, options)\n } finally {\n el.classList.remove('is-exporting')\n }\n}\n\n/** Draws every widget, waits for their data, and opens the browser's print dialog. */\nasync function print() {\n await settle()\n window.print()\n}\n\n// printing from the browser's menu: draw what is far from the view, as far as there is time\nfunction onBeforePrint() {\n showAll.value = true\n}\nonMounted(() => window.addEventListener('beforeprint', onBeforePrint))\nonBeforeUnmount(() => window.removeEventListener('beforeprint', onBeforePrint))\n\n// ---------------------------------------------------------------------------\n// Announcements\n\nconst live = ref('')\nfunction say(text: string) {\n live.value = ''\n requestAnimationFrame(() => (live.value = text))\n}\n\nconst breakpointName = shallowRef(main.value.name)\nfunction onBreakpoint(name: string) {\n breakpointName.value = name\n emit('breakpointChange', name)\n}\n\nconst minHeight = computed(() => {\n const gap = Array.isArray(props.gap) ? props.gap[1] : props.gap\n return `${props.rowHeight * 3 + gap * 2}px`\n})\n\ndefineExpose<DashboardExpose>({\n transaction,\n dispatch,\n undo,\n redo,\n get canUndo() {\n return canUndo.value\n },\n get canRedo() {\n return canRedo.value\n },\n addWidget,\n removeWidget,\n duplicateWidget,\n focusWidget,\n openSettings,\n openFullscreen,\n startAdd,\n get types() {\n return props.widgets\n },\n get breakpoint() {\n return grid.value?.breakpoint ?? breakpointName.value\n },\n get editable() {\n return props.editable\n },\n get document() {\n return model.value\n },\n get filters() {\n return values.value\n },\n get linkedFilters() {\n return [...links.value.values()]\n },\n setFilter: (key, value, options) => setFilter(undefined, key, value, options),\n clearFilters,\n refresh: (source) => store.reload(source),\n exportPNG,\n exportWidget: exportWidget as DashboardExpose['exportWidget'],\n saveWidget: saveWidget as DashboardExpose['saveWidget'],\n print,\n})\n</script>\n\n<template>\n <div\n ref=\"root\"\n :class=\"['dou-dashboard', editable && 'is-editable']\"\n role=\"region\"\n :aria-label=\"label || messages.dashboard\"\n tabindex=\"-1\"\n @keydown=\"onKeydown\"\n @copy=\"onCopy($event)\"\n @cut=\"onCopy($event, true)\"\n @paste=\"onPaste\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <GridLayout\n ref=\"grid\"\n :model-value=\"items\"\n :layouts=\"layouts\"\n :columns=\"columns\"\n :breakpoints=\"breakpoints\"\n :row-height=\"rowHeight\"\n :gap=\"gap\"\n :compact=\"compact\"\n :editable=\"editable\"\n :handle=\"true\"\n :item-label=\"labelOf\"\n :messages=\"messages\"\n :style=\"editable && !model.widgets.length ? { minHeight } : undefined\"\n @update:model-value=\"(list) => gather({ items: list })\"\n @update:layouts=\"(next) => gather({ layouts: next })\"\n @drop=\"onDrop\"\n @drag-start=\"onDragStart\"\n @drag-end=\"onDragEnd\"\n @breakpoint-change=\"onBreakpoint\"\n >\n <template #item=\"{ item }\">\n <WidgetFrame :id=\"item.id\" />\n </template>\n </GridLayout>\n <div v-if=\"editable && !model.widgets.length\" class=\"dou-dashboard__empty\">\n <DouEmpty size=\"sm\" :title=\"messages.emptyTitle\" :description=\"messages.emptyHint\">\n <template #icon><LayoutGridPlusIcon /></template>\n </DouEmpty>\n </div>\n <div class=\"dou-dashboard__live\" aria-live=\"polite\" aria-atomic=\"true\">{{ live }}</div>\n <DouDrawer\n :open=\"!!settingsWidget\"\n :title=\"\n settingsWidget ? format(messages.settingsTitle, { title: titleOf(settingsWidget) }) : ''\n \"\n :size=\"360\"\n @update:open=\"(open) => !open && (settingsId = undefined)\"\n @closed=\"restoreFocus\"\n >\n <div v-if=\"settingsWidget\" class=\"dou-dashboard__settings\">\n <label class=\"dou-dashboard__field\">\n <span class=\"dou-dashboard__field-label\">{{ messages.titleField }}</span>\n <DouInput\n :model-value=\"settingsWidget.title ?? ''\"\n :placeholder=\"typeOf(settingsWidget)?.label ?? settingsWidget.type\"\n @update:model-value=\"\n (value) =>\n run(\n [\n {\n type: 'update',\n id: settingsWidget!.id,\n patch: { title: value || undefined },\n },\n ],\n { origin: 'settings', group: `title:${settingsWidget!.id}` },\n )\n \"\n />\n </label>\n <WidgetSettings\n v-if=\"typeOf(settingsWidget)?.settings\"\n :widget=\"settingsWidget\"\n :type=\"typeOf(settingsWidget)!\"\n :set-props=\"setProps\"\n @update:props=\"\n (value) =>\n run([{ type: 'update', id: settingsWidget!.id, patch: { props: value } }], {\n origin: 'settings',\n group: `props:${settingsWidget!.id}`,\n })\n \"\n />\n </div>\n </DouDrawer>\n <DouDialog\n :open=\"!!fullscreenWidget\"\n :title=\"fullscreenWidget ? titleOf(fullscreenWidget) : ''\"\n fullscreen\n @update:open=\"(open) => !open && (fullscreenId = undefined)\"\n @closed=\"restoreFocus\"\n >\n <WidgetBody\n v-if=\"fullscreenWidget\"\n class=\"is-fullscreen\"\n :widget=\"fullscreenWidget\"\n :type=\"typeOf(fullscreenWidget)\"\n :editing=\"false\"\n fullscreen\n :messages=\"messages\"\n :set-props=\"setProps\"\n />\n </DouDialog>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"dashboard.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_normalizeClass","_unref","_createVNode","GridLayout","_normalizeStyle","_withCtx","WidgetFrame","_createCommentVNode","_createElementVNode","_toDisplayString","_createBlock","CommentCard","WidgetSettings","CommentButton","WidgetBody"],"sources":["../../src/dashboard/dashboard.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { LayoutGridPlusIcon, fileIconOf } from '@dou-ui/icons'\nimport type { SheetExporter, SheetWorkbook } from '@dou-ui/sheet/core'\nimport {\n DouDialog,\n DouDrawer,\n DouEmpty,\n DouInput,\n downloadBlob,\n matchesHotkey,\n useLocale,\n} from 'dou-ui'\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n provide,\n ref,\n shallowReactive,\n shallowRef,\n toRaw,\n watch,\n} from 'vue'\nimport { emptyDocument } from '../core/document'\nimport { DashboardHistory } from '../core/history'\nimport {\n applySteps,\n cloneJson,\n DashboardTransaction,\n replaceWidgets,\n sameValue,\n} from '../core/transaction'\nimport type { DashboardStep, DashboardTransactionMeta } from '../core/transaction'\nimport type { DashboardDocument, DashboardPlace, DashboardWidget } from '../core/types'\nimport type {\n DashboardPeer,\n DashboardPresence,\n DashboardPresenceAction,\n} from '../core/collaboration'\nimport { dataContextKey } from '../data/context'\nimport { filterText, isEmptyFilter } from '../data/filters'\nimport { createSourceStore, sameSource } from '../data/store'\nimport type {\n DashboardFilters,\n DashboardLinkedFilter,\n DashboardSetFilterOptions,\n} from '../data/types'\nimport GridLayout from '../grid/grid-layout.vue'\nimport { DEFAULT_BREAKPOINTS, DEFAULT_COLUMNS, gridTiers } from '../grid/tiers'\nimport type { GridDragEvent, GridDropEvent, GridLayoutExpose, GridLayouts } from '../grid/types'\nimport { findPlace, fitItem, moveItem } from '../layout/engine'\nimport type { GridItem, GridLayoutOptions } from '../layout/types'\nimport { format, useDashboardMessages } from '../locale'\nimport { DEFAULT_WIDGET_SIZE, defaultPropsOf } from '../widget/define'\nimport type { DashboardWidgetType } from '../widget/define'\nimport type {\n DashboardAddOptions,\n DashboardEmits,\n DashboardExportErrorEvent,\n DashboardExportOptions,\n DashboardExpose,\n DashboardSaveOptions,\n DashboardProps,\n} from './types'\nimport { createObservers, observersKey } from './observers'\nimport { elementToPNG } from './export'\nimport type { DashboardImageOptions } from './export'\nimport WidgetBody from './widget-body.vue'\nimport WidgetFrame from './widget-frame.vue'\nimport WidgetSettings from './widget-settings.vue'\nimport { frameContextKey } from './frame-context'\nimport CommentButton from './comment-button.vue'\nimport CommentCard from './comment-card.vue'\nimport { useDashboardComments } from './comments'\nimport type { FrameExporter, WidgetAction } from './frame-context'\n\ndefineOptions({ name: 'DouDashboard' })\n\nconst props = withDefaults(defineProps<Omit<DashboardProps, 'modelValue' | 'filters'>>(), {\n widgets: () => [],\n columns: () => DEFAULT_COLUMNS,\n breakpoints: () => DEFAULT_BREAKPOINTS,\n rowHeight: 80,\n gap: 16,\n compact: 'vertical',\n comments: undefined,\n author: undefined,\n activeComment: undefined,\n commentable: true,\n})\nconst emit = defineEmits<Omit<DashboardEmits, 'update:modelValue' | 'update:filters'>>()\nconst model = defineModel<DashboardDocument>({ default: emptyDocument })\nconst filters = defineModel<DashboardFilters>('filters', { default: () => ({}) })\nconst messages = useDashboardMessages(() => props.messages)\n\nconst grid = ref<GridLayoutExpose>()\nconst observers = createObservers()\nprovide(observersKey, observers)\nonBeforeUnmount(() => observers.dispose())\n/** This many widgets are drawn in full at once, the rest when they come near the view. */\nconst EAGER = 16\nconst root = ref<HTMLElement>()\n\nconst typeMap = computed(() => new Map(props.widgets.map((type) => [type.type, type])))\nconst typeOf = (widget: DashboardWidget) => typeMap.value.get(widget.type)\nconst widgetMap = computed(() => new Map(model.value.widgets.map((widget) => [widget.id, widget])))\n/** The first widgets of the document, drawn in full without waiting to be seen. */\nconst eagerIds = computed(() => new Set(model.value.widgets.slice(0, EAGER).map((w) => w.id)))\n/** Widgets added once the dashboard is up are drawn in full straight away (not reactive on purpose). */\nlet mounted = false\nonMounted(() => (mounted = true))\nconst isEager = (id: string) => mounted || eagerIds.value.has(id)\nconst titleOf = (widget: DashboardWidget) => widget.title || typeOf(widget)?.label || widget.type\n\nconst tiers = computed(() => gridTiers(props.columns, props.breakpoints))\n/** The widest breakpoint: its places are the main ones. */\nconst main = computed(() => tiers.value[0]!)\nconst mainOptions = computed<GridLayoutOptions>(() => ({\n columns: Math.max(1, Math.round(main.value.columns)),\n compact: props.compact,\n}))\n\n// ---------------------------------------------------------------------------\n// Changes and history\n\nconst history = new DashboardHistory()\n/** Bumped whenever the history changes, so `canUndo` and `canRedo` update. */\nconst historyVersion = ref(0)\n/** The document last emitted, to tell our own changes from the app's. */\nlet emitted: DashboardDocument | undefined\nwatch(model, (doc) => {\n // the app may hand back a reactive copy of what was emitted\n // a document the app put in itself: the old steps no longer fit it\n if (toRaw(doc) === emitted) return\n history.clear()\n historyVersion.value++\n})\n\nfunction commit(tr: DashboardTransaction) {\n emitted = toRaw(tr.doc)\n model.value = tr.doc\n emit('change', tr)\n}\n\n/** A transaction on the document as it is now, to `dispatch`. */\nfunction transaction() {\n return new DashboardTransaction(model.value)\n}\n\n/** Makes the changes of a transaction, as one undo step (or part of one, by `meta.group`). */\nfunction dispatch(tr: DashboardTransaction) {\n if (toRaw(tr.before) !== toRaw(model.value))\n throw new Error(\n '[@dou-ui/dashboard] the transaction was made on another version of the dashboard',\n )\n if (!tr.changed) return\n const shared = props.collaboration\n if (!shared) {\n history.record(tr)\n historyVersion.value++\n }\n commit(tr)\n shared?.transaction(tr)\n}\n\n/** Steps made into a transaction and dispatched, for the dashboard's own changes. */\nfunction run(steps: DashboardStep[], meta: DashboardTransactionMeta) {\n const tr = applySteps(model.value, steps, meta)\n dispatch(tr)\n return tr\n}\n\n// ---------------------------------------------------------------------------\n// Comments on widgets\n\nconst comments = useDashboardComments({\n props,\n emit,\n model,\n run,\n carry: (id, patch) => history.carry(id, patch),\n})\n/** The full screen view, which has a comment button of its own. */\nconst fullscreenBody = shallowRef<HTMLElement | null>(null)\n/** A widget's comment button: in the full screen view while that widget is there. */\nfunction buttonOf(id: string) {\n const selector = `[data-dou-comment=\"${CSS.escape(id)}\"]`\n const inFullscreen = fullscreenId.value === id ? fullscreenBody.value : null\n return (\n inFullscreen?.querySelector<HTMLElement>(selector) ??\n root.value?.querySelector<HTMLElement>(selector) ??\n null\n )\n}\n/** Where a widget's card goes: by its comment button, or by the widget until the button is drawn. */\nconst cardSpotOf = (id: string) =>\n buttonOf(id) ??\n root.value?.querySelector<HTMLElement>(`[data-grid-id=\"${CSS.escape(id)}\"]`) ??\n null\n/** The comment shortcut in the full screen view, which is outside the dashboard. */\nfunction onFullscreenKeydown(event: KeyboardEvent) {\n const id = fullscreenId.value\n if (!id || event.defaultPrevented || !comments.enabled.value || isTyping(event.target)) return\n if (matchesHotkey(event, 'mod+alt+m') && comments.start(id)) event.preventDefault()\n}\n// A thread opened from outside, e.g. a list beside the dashboard: bring its widget into view.\nwatch(\n () => props.activeComment,\n (id) => {\n const widget = id && !comments.openedHere(id) ? comments.widgetOf(id) : null\n if (widget) grid.value?.scrollToItem(widget)\n },\n)\n\nfunction undo() {\n if (props.collaboration) return props.collaboration.undo()\n const tr = history.undo(model.value)\n historyVersion.value++\n if (!tr) return false\n if (tr.changed) commit(tr)\n return true\n}\n\nfunction redo() {\n if (props.collaboration) return props.collaboration.redo()\n const tr = history.redo(model.value)\n historyVersion.value++\n if (!tr) return false\n if (tr.changed) commit(tr)\n return true\n}\n\nconst canUndo = computed(() =>\n props.collaboration ? props.collaboration.canUndo() : (historyVersion.value, history.canUndo),\n)\nconst canRedo = computed(() =>\n props.collaboration ? props.collaboration.canRedo() : (historyVersion.value, history.canRedo),\n)\n\n// ---------------------------------------------------------------------------\n// The grid: widgets as items, places by breakpoint\n\nfunction limitsOf(type: DashboardWidgetType<any> | undefined) {\n const size = type?.size ?? DEFAULT_WIDGET_SIZE\n return {\n w: size.w,\n h: size.h,\n minW: size.minW,\n maxW: size.maxW,\n minH: size.minH,\n maxH: size.maxH,\n }\n}\n\n/** The widgets on the widest breakpoint; those without a place there get the first spot they fit. */\nconst placeOf = (item: DashboardPlace): DashboardPlace => ({\n x: item.x,\n y: item.y,\n w: item.w,\n h: item.h,\n})\n\n// The item of a widget that didn't change is the same object as before, so\n// the grid and its other items have nothing to draw again.\nlet itemCache = new WeakMap<DashboardWidget, GridItem>()\nwatch([typeMap, main], () => (itemCache = new WeakMap()), { flush: 'sync' })\nconst items = computed<GridItem[]>(() => {\n const name = main.value.name\n const options = mainOptions.value\n const placed: GridItem[] = []\n const result = new Map<string, GridItem>()\n const missing: DashboardWidget[] = []\n for (const widget of model.value.widgets) {\n const raw = toRaw(widget)\n const place = raw.place[name]\n if (!place) {\n missing.push(raw)\n continue\n }\n let item = itemCache.get(raw)\n if (!item) {\n const { minW, maxW, minH, maxH } = limitsOf(typeOf(raw))\n item = { id: raw.id, ...placeOf(place), minW, maxW, minH, maxH }\n itemCache.set(raw, item)\n }\n placed.push(item)\n result.set(raw.id, item)\n }\n for (const widget of missing) {\n const fitted = fitItem(\n { id: widget.id, x: 0, y: 0, ...limitsOf(typeOf(widget)) },\n options.columns,\n )\n const item = { ...fitted, ...findPlace(placed, fitted, options) }\n placed.push(item)\n result.set(widget.id, item)\n }\n return model.value.widgets.map((widget) => result.get(widget.id)!)\n})\n\n/** The places on the narrower breakpoints. */\nconst layouts = computed<GridLayouts>(() => {\n const result: GridLayouts = {}\n for (const tier of tiers.value.slice(1)) {\n const list = []\n for (const widget of model.value.widgets) {\n const place = widget.place[tier.name]\n if (place) list.push({ id: widget.id, ...place })\n }\n if (list.length) result[tier.name] = list\n }\n return result\n})\n\n// The grid tells a move with `update:modelValue`, `update:layouts` and\n// `drop` one after another; they are gathered into one change.\nlet pending: { items?: GridItem[]; layouts?: GridLayouts; drop?: { id: string; type: string } } = {}\nlet flushing = false\nfunction gather(part: typeof pending) {\n Object.assign(pending, part)\n if (flushing) return\n flushing = true\n queueMicrotask(flush)\n}\n\nfunction flush() {\n flushing = false\n const { items: list, layouts: saved, drop } = pending\n pending = {}\n const doc = model.value\n const places = new Map<string, DashboardWidget['place']>()\n const setPlace = (id: string, name: string, item: DashboardPlace) => {\n let place = places.get(id)\n if (!place) places.set(id, (place = { ...widgetMap.value.get(id)?.place }))\n place[name] = placeOf(item)\n }\n for (const item of list ?? []) setPlace(item.id, main.value.name, item)\n for (const [name, others] of Object.entries(saved ?? {}))\n for (const item of others ?? []) setPlace(item.id, name, item)\n const steps: DashboardStep[] = []\n for (const [id, place] of places) {\n if (widgetMap.value.has(id)) {\n steps.push({ type: 'update', id, patch: { place } })\n } else if (drop?.id === id) {\n const type = typeMap.value.get(drop.type)\n if (type)\n steps.push({ type: 'add', widget: newWidget(id, type, place), index: doc.widgets.length })\n }\n }\n const tr = run(steps, { origin: drop ? 'drop' : 'layout' })\n if (drop && tr.changed) {\n const widget = widgetMap.value.get(drop.id)\n if (widget) say(format(messages.value.added, { item: titleOf(widget) }))\n }\n}\n\nfunction onDrop(event: GridDropEvent) {\n const data = event.data as { type?: string } | undefined\n if (data?.type) gather({ drop: { id: event.item.id, type: data.type } })\n}\n\nconst dragging = ref(false)\n\n// ---------------------------------------------------------------------------\n// Adding, copying and removing\n\nfunction newId(type: string) {\n const used = widgetMap.value\n for (;;) {\n const id = props.createId?.(type) ?? `${type}-${Math.random().toString(36).slice(2, 8)}`\n if (!used.has(id)) return id\n if (props.createId)\n throw new Error(`[@dou-ui/dashboard] createId gave \"${id}\", which is already in use`)\n }\n}\n\nfunction newWidget(\n id: string,\n type: DashboardWidgetType<any>,\n place: DashboardWidget['place'],\n options: Pick<DashboardAddOptions, 'title' | 'props'> = {},\n): DashboardWidget {\n const widget: DashboardWidget = { id, type: type.type, place }\n if (options.title) widget.title = options.title\n const initial = defaultPropsOf(type)\n if (initial || options.props) widget.props = { ...initial, ...options.props }\n return widget\n}\n\n/**\n * Puts a new item on the widest breakpoint, at `at` (pushing the others\n * away) or in the first spot it fits; the steps also move any widget it\n * pushed.\n */\nfunction placeNew(item: GridItem, at: Pick<DashboardPlace, 'x' | 'y'> | undefined) {\n const options = mainOptions.value\n const fitted = fitItem(item, options.columns)\n const spot = at ?? findPlace(items.value, fitted, options)\n const layout = moveItem([...items.value, { ...fitted, ...spot }], item.id, spot, options)\n const steps: DashboardStep[] = []\n let place: DashboardPlace = { ...fitted, ...spot }\n for (const next of layout) {\n if (next.id === item.id) {\n place = placeOf(next)\n continue\n }\n const widget = widgetMap.value.get(next.id)\n const old = widget && items.value.find((other) => other.id === next.id)\n if (widget && old && (old.x !== next.x || old.y !== next.y))\n steps.push({\n type: 'update',\n id: next.id,\n patch: { place: { ...widget.place, [main.value.name]: placeOf(next) } },\n })\n }\n return { place, steps }\n}\n\nfunction addWidget(typeName: string, options: DashboardAddOptions = {}) {\n const type = typeMap.value.get(typeName)\n if (!type) return undefined\n const id = newId(typeName)\n const { place, steps } = placeNew({ id, x: 0, y: 0, ...limitsOf(type) }, options.at)\n const widget = newWidget(id, type, { [main.value.name]: place }, options)\n run([{ type: 'add', widget, index: model.value.widgets.length }, ...steps], {\n origin: 'api',\n })\n say(format(messages.value.added, { item: titleOf(widget) }))\n if (options.focus !== false) void nextTick(() => focusWidget(id))\n return id\n}\n\n/** Adds a copy of a widget (from this dashboard or the clipboard) beside `near`, or in the first free spot. */\nfunction addCopy(source: DashboardWidget, near?: GridItem) {\n const type = typeOf(source)\n const id = newId(source.type)\n const columns = mainOptions.value.columns\n const size = near ?? { ...limitsOf(type), ...source.place[main.value.name] }\n const at = near\n ? near.x + near.w * 2 <= columns\n ? { x: near.x + near.w, y: near.y }\n : { x: near.x, y: near.y + near.h }\n : undefined\n const { place, steps } = placeNew({ ...limitsOf(type), id, x: 0, y: 0, w: size.w, h: size.h }, at)\n const widget: DashboardWidget = {\n ...cloneJson(source),\n id,\n place: { [main.value.name]: place },\n }\n // a copy starts without the original's discussions\n delete widget.comments\n const index = near\n ? model.value.widgets.findIndex((other) => other.id === near.id) + 1\n : model.value.widgets.length\n run([{ type: 'add', widget, index }, ...steps], { origin: 'copy' })\n say(format(messages.value.added, { item: titleOf(widget) }))\n void nextTick(() => focusWidget(id))\n return id\n}\n\nfunction duplicateWidget(id: string) {\n const widget = widgetMap.value.get(id)\n const item = items.value.find((other) => other.id === id)\n return widget && item ? addCopy(widget, item) : undefined\n}\n\nfunction removeWidget(id: string) {\n const list = model.value.widgets\n const index = list.findIndex((widget) => widget.id === id)\n if (index < 0) return\n const widget = list[index]!\n const hadFocus = root.value?.contains(document.activeElement)\n const neighbour = list[index + 1] ?? list[index - 1]\n if (settingsId.value === id) settingsId.value = undefined\n if (fullscreenId.value === id) fullscreenId.value = undefined\n run([{ type: 'remove', id }], { origin: 'api' })\n say(format(messages.value.removed, { item: titleOf(widget) }))\n if (hadFocus) void nextTick(() => (neighbour ? focusWidget(neighbour.id) : root.value?.focus()))\n}\n\nfunction focusWidget(id: string) {\n grid.value?.focusItem(id)\n}\n\n/** The widget being dragged in, which has no widget yet: its name is its type's. */\nlet adding: { id: string; label: string } | undefined\n\nfunction startAdd(event: PointerEvent, typeName: string) {\n const type = typeMap.value.get(typeName)\n if (!type || !props.editable) return\n adding = { id: newId(typeName), label: type.label }\n grid.value?.startDrop(event, { id: adding.id, ...limitsOf(type) }, { type: typeName })\n}\n\nfunction labelOf(item: GridItem) {\n const widget = widgetMap.value.get(item.id)\n return widget ? titleOf(widget) : item.id === adding?.id ? adding.label : item.id\n}\n\nfunction setProps(id: string, patch: Record<string, unknown>, options: { group?: string } = {}) {\n const widget = widgetMap.value.get(id)\n if (!widget) return\n run([{ type: 'update', id, patch: { props: { ...widget.props, ...patch } } }], {\n origin: 'widget',\n group: options.group,\n })\n}\n\nfunction rename(id: string, title: string) {\n run([{ type: 'update', id, patch: { title: title.trim() || undefined } }], {\n origin: 'title',\n })\n}\n\n// ---------------------------------------------------------------------------\n// Settings and full screen\n\nconst settingsId = ref<string>()\nconst settingsWidget = computed(() =>\n settingsId.value ? widgetMap.value.get(settingsId.value) : undefined,\n)\nconst fullscreenId = ref<string>()\nconst fullscreenWidget = computed(() =>\n fullscreenId.value ? widgetMap.value.get(fullscreenId.value) : undefined,\n)\n/** The widget to give focus back to when a drawer or dialog closes. */\nlet returnTo: string | undefined\n\nfunction openSettings(id: string) {\n if (!props.editable || !widgetMap.value.has(id)) return\n returnTo = id\n settingsId.value = id\n}\n\nfunction openFullscreen(id: string) {\n const widget = widgetMap.value.get(id)\n if (!widget || typeOf(widget)?.fullscreen === false) return\n returnTo = id\n fullscreenId.value = id\n}\n\nfunction restoreFocus() {\n const id = returnTo\n returnTo = undefined\n if (id && widgetMap.value.has(id)) focusWidget(id)\n}\n\nwatch(\n () => props.editable,\n (editable) => {\n if (!editable) settingsId.value = undefined\n },\n)\n\nfunction onAction(id: string, action: WidgetAction) {\n if (action === 'settings') openSettings(id)\n else if (action === 'fullscreen') openFullscreen(id)\n else if (action === 'duplicate') duplicateWidget(id)\n else removeWidget(id)\n}\n\n// ---------------------------------------------------------------------------\n// Editing together\n\n/** Changes from others wait while a widget is dragged here; then the shared document is read again. */\nlet held = false\n\nfunction applyShared(doc: DashboardDocument, origin: 'remote' | 'undo' | 'redo') {\n if (dragging.value) {\n held = true\n return\n }\n const tr = replaceWidgets(new DashboardTransaction(model.value), doc, { keepComments: false })\n if (!tr.changed) return\n tr.setMeta('history', false).setMeta('origin', origin)\n const ids = new Set(tr.doc.widgets.map((widget) => widget.id))\n if (settingsId.value && !ids.has(settingsId.value)) settingsId.value = undefined\n if (fullscreenId.value && !ids.has(fullscreenId.value)) fullscreenId.value = undefined\n commit(tr)\n}\n\n// one written in the template is new on every render: each one starts over and clears undo\nlet setupTimes: number[] = []\nlet setupWarned = false\nfunction warnRepeatedSetup() {\n if (process.env.NODE_ENV === 'production' || setupWarned) return\n const now = Date.now()\n setupTimes = [...setupTimes.filter((time) => now - time < 1000), now]\n if (setupTimes.length < 4) return\n setupWarned = true\n console.warn(\n '[@dou-ui/dashboard] collaboration keeps being replaced, which starts it over and clears undo each time. Create it once in <script setup> instead of in the template.',\n )\n}\n\nwatch(\n () => props.collaboration,\n (shared, _, onCleanup) => {\n if (shared) warnRepeatedSetup()\n history.clear()\n historyVersion.value++\n if (!shared) return\n const stop = shared.setup({ document: () => model.value, apply: applyShared })\n onCleanup(() => {\n shared.presence?.(null)\n stop()\n })\n },\n { immediate: true },\n)\n\n/** The widget being moved or resized here, and how. */\nconst drag = shallowRef<GridDragEvent>()\nfunction onDragStart(event: GridDragEvent) {\n dragging.value = true\n drag.value = event\n}\nfunction onDragEnd() {\n dragging.value = false\n drag.value = undefined\n if (!held) return\n held = false\n // after the drop's own change, which the grid hands over in a microtask\n queueMicrotask(() => queueMicrotask(() => props.collaboration?.sync()))\n}\n\n/** The widget whose item, or a control in it, has focus. */\nconst focused = ref<string>()\nfunction onFocusIn(event: FocusEvent) {\n const item = (event.target as HTMLElement).closest?.<HTMLElement>('[data-grid-id]')\n focused.value = item?.closest('.dou-dashboard') === root.value ? item?.dataset.gridId : undefined\n}\nfunction onFocusOut(event: FocusEvent) {\n if (!root.value?.contains(event.relatedTarget as Node | null)) focused.value = undefined\n}\n\n/** What this person is doing, shown to the others. */\nconst presence = computed<DashboardPresence | null>(() => {\n const moving = drag.value\n if (moving && moving.kind !== 'drop' && widgetMap.value.has(moving.id))\n return { widget: moving.id, action: moving.kind as DashboardPresenceAction }\n if (settingsId.value) return { widget: settingsId.value, action: 'settings' }\n if (focused.value && widgetMap.value.has(focused.value))\n return { widget: focused.value, action: 'focus' }\n return null\n})\nwatch(\n [presence, () => props.collaboration] as const,\n ([current, shared], previous) => {\n if (!shared?.presence) return\n const [before, sharedBefore] = previous ?? []\n if (\n sharedBefore === shared &&\n before?.widget === current?.widget &&\n before?.action === current?.action\n )\n return\n shared.presence(current)\n },\n { immediate: true },\n)\nconst NO_PEERS: readonly DashboardPeer[] = []\n\nprovide(frameContextKey, {\n comments,\n widget: (id) => widgetMap.value.get(id),\n type: typeOf,\n title: titleOf,\n editing: () => props.editable,\n messages: () => messages.value,\n eager: isEager,\n all: () => showAll.value,\n setProps,\n action: onAction,\n rename,\n linked: (id) => linksByWidget.value.get(id) ?? NO_LINKS,\n clearFilter: (key) => setFilter(undefined, key, undefined),\n peers: (id) => props.collaboration?.peers?.(id) ?? NO_PEERS,\n setWorkbook,\n exporters: (id) => (workbooks.has(id) ? exporterList.value : NO_EXPORTERS),\n exportTo: exportFromMenu,\n exporting: (id) => exporting.has(id),\n setDrawn: (id, drawn) => (drawn ? drawnIds.add(id) : drawnIds.delete(id)),\n exportError: (id) => exportErrors.get(id),\n clearExportError: (id) => exportErrors.delete(id),\n})\n\n// ---------------------------------------------------------------------------\n// Exporting a widget's content as a file\n\n/** How each mounted widget gives its content as a workbook; see `setWorkbook`. */\nconst workbooks = shallowReactive(new Map<string, () => SheetWorkbook | undefined>())\nfunction setWorkbook(id: string, get: () => SheetWorkbook | undefined) {\n workbooks.set(id, get)\n return () => {\n if (workbooks.get(id) === get) workbooks.delete(id)\n }\n}\n\n// the file code comes with the first exporter, in a chunk of its own\ntype SheetCore = typeof import('@dou-ui/sheet/core')\nconst sheetCore = shallowRef<SheetCore>()\nlet loadingCore: Promise<SheetCore> | undefined\nfunction loadSheetCore() {\n loadingCore ??= import('@dou-ui/sheet/core').then((core) => (sheetCore.value = core))\n return loadingCore\n}\nwatch(\n () => props.exporters?.length,\n (count) => count && void loadSheetCore(),\n { immediate: true },\n)\n\nconst NO_EXPORTERS: FrameExporter[] = []\nconst { locale } = useLocale()\n/** The exporters of the menu, without those that draw a sheet's grid. */\nconst exporterList = computed<FrameExporter[]>(() => {\n const core = sheetCore.value\n if (!core) return NO_EXPORTERS\n const sheetMessages = core.sheetMessagesFor(locale.value.name)\n return (props.exporters ?? [])\n .filter((exporter) => exporter.needs !== 'view')\n .map((exporter) => ({\n name: exporter.name,\n label: typeof exporter.label === 'function' ? exporter.label(sheetMessages) : exporter.label,\n icon: exporter.icon ?? fileIconOf(exporter.extension),\n }))\n})\n\nfunction exporterOf(exporter: string | SheetExporter) {\n if (typeof exporter !== 'string') return exporter\n const found = props.exporters?.find((item) => item.name === exporter)\n if (!found) throw new RangeError(`[@dou-ui/dashboard] there is no exporter \"${exporter}\"`)\n return found\n}\n\n/** A widget's file and sheet name: its title, or its type's name. */\nconst exportNameOf = (widget: DashboardWidget) => titleOf(widget).trim() || widget.type\n\n/** Why something failed, as people read it: a file error's `reason`, or its message. */\nfunction reasonOf(error: unknown) {\n if (error instanceof Error)\n return 'reason' in error && typeof error.reason === 'string' ? error.reason : error.message\n return String(error)\n}\n\n/**\n * A widget's content as a file: its workbook written by the exporter, a\n * name from `exporters` or an exporter itself. Waits for the data shown,\n * and draws the widget first when it is far from the view.\n */\nasync function exportWidget(\n id: string,\n exporter: string | SheetExporter,\n options: DashboardExportOptions = {},\n): Promise<Blob> {\n const chosen = exporterOf(exporter)\n const widget = widgetMap.value.get(id)\n if (!widget) throw new RangeError(`[@dou-ui/dashboard] there is no widget \"${id}\"`)\n const core = await loadSheetCore()\n // a widget drawn already that gives no workbook never will: no need to draw them all\n await settle(5000, !drawnIds.has(id))\n options.signal?.throwIfAborted()\n const get = workbooks.get(id)\n const book = get?.()\n if (!book)\n throw new core.SheetFileError(\n get\n ? `[@dou-ui/dashboard] the widget \"${id}\" has no data to export now`\n : `[@dou-ui/dashboard] the widget \"${id}\" doesn't give its content as a workbook (setWorkbook)`,\n 'empty',\n messages.value.nothingToExport,\n )\n // sheets without a name take the widget's, as the file does\n const name = exportNameOf(widget)\n const named = book.sheets.some((sheet) => !sheet.name)\n ? { ...book, sheets: book.sheets.map((sheet) => (sheet.name ? sheet : { ...sheet, name })) }\n : book\n return core.exportWorkbook(named, chosen, {\n options: options.options,\n signal: options.signal,\n locale: locale.value.name,\n })\n}\n\n/** The widgets drawn in full; the others show only their title until they come near. */\nconst drawnIds = new Set<string>()\n\n/** Why the last export from each widget's menu failed, shown over its content until closed. */\nconst exportErrors = shallowReactive(new Map<string, string>())\n/** The widgets exporting now, whose export button waits. */\nconst exporting = shallowReactive(new Set<string>())\n\n/**\n * Exports a widget's content and saves the file in the downloads, as its\n * menu does. A failure shows over the widget and comes as `exportError`,\n * and the promise rejects.\n */\nasync function saveWidget(\n id: string,\n exporter: string | SheetExporter,\n options: DashboardSaveOptions = {},\n): Promise<void> {\n const chosen = exporterOf(exporter)\n const widget = widgetMap.value.get(id)\n if (!widget) throw new RangeError(`[@dou-ui/dashboard] there is no widget \"${id}\"`)\n const name = options.fileName ?? `${exportNameOf(widget)}.${chosen.extension}`\n exportErrors.delete(id)\n exporting.add(id)\n let blob: Blob\n try {\n blob = await exportWidget(id, chosen, options)\n } catch (error) {\n const event: DashboardExportErrorEvent = {\n widget: id,\n exporter: chosen.name,\n error,\n message: format(messages.value.exportFailed, { name, reason: reasonOf(error) }),\n defaultPrevented: false,\n preventDefault() {\n this.defaultPrevented = true\n },\n }\n emit('exportError', event)\n // the notice is read out itself; told by the app, it is only read out\n if (event.defaultPrevented) say(event.message)\n else exportErrors.set(id, event.message)\n throw error\n } finally {\n exporting.delete(id)\n }\n downloadBlob(blob, name)\n say(format(messages.value.exported, { name }))\n}\n\nfunction exportFromMenu(id: string, name: string) {\n if (exporting.has(id)) return\n // the failure is shown over the widget\n saveWidget(id, name).catch(() => {})\n}\n\n// ---------------------------------------------------------------------------\n// Data and filters\n\nconst store = createSourceStore(() => props.sources)\nonBeforeUnmount(() => store.dispose())\n// a source replaced by one that loads differently loads again\nwatch(\n () => props.sources,\n (next, previous) => {\n const names = new Set([...Object.keys(previous ?? {}), ...Object.keys(next ?? {})])\n for (const name of names) if (!sameSource(previous?.[name], next?.[name])) store.reload(name)\n },\n)\n\n/** The filters set by widgets, by key: they apply to every widget but the one that set them. */\nconst links = shallowRef(new Map<string, DashboardLinkedFilter>())\nconst EMPTY_SET: ReadonlySet<string> = new Set()\nconst NO_LINKS: DashboardLinkedFilter[] = []\nconst linksByWidget = computed(() => {\n const result = new Map<string, DashboardLinkedFilter[]>()\n for (const link of links.value.values()) {\n const list = result.get(link.widget)\n if (list) list.push(link)\n else result.set(link.widget, [link])\n }\n return result\n})\nconst emittedByWidget = computed(() => {\n const result = new Map<string, Set<string>>()\n for (const [id, list] of linksByWidget.value)\n result.set(id, new Set(list.map((link) => link.key)))\n return result\n})\n\n// The values as set last: with `v-model:filters` the model only updates once\n// the parent draws again, so several filters set at once build on this.\nconst values = shallowRef<DashboardFilters>(filters.value)\nwatch(filters, (next) => (values.value = next))\n\nfunction setFilter(\n widget: string | undefined,\n key: string,\n value: unknown,\n options: DashboardSetFilterOptions = {},\n) {\n const next = { ...values.value }\n const nextLinks = new Map(links.value)\n if (isEmptyFilter(value)) delete next[key]\n else next[key] = value\n if (widget && !isEmptyFilter(value) && widgetMap.value.has(widget))\n nextLinks.set(key, { key, value, label: options.label ?? filterText(value), widget })\n else nextLinks.delete(key)\n links.value = nextLinks\n values.value = next\n filters.value = next\n}\n\nfunction clearFilters() {\n links.value = new Map()\n values.value = {}\n filters.value = {}\n}\n\n// a filter changed from outside (the filter bar, the app) is no longer the widget's\nwatch(filters, (current) => {\n let next: Map<string, DashboardLinkedFilter> | undefined\n for (const [key, link] of links.value) {\n if (sameValue(current[key], link.value)) continue\n next ??= new Map(links.value)\n next.delete(key)\n }\n if (next) links.value = next\n})\n\n// the filters of a widget that is removed go with it\nwatch(widgetMap, (map) => {\n for (const link of links.value.values())\n if (!map.has(link.widget)) setFilter(undefined, link.key, undefined)\n})\n\nconst sourceNames = computed(() => Object.keys(props.sources ?? {}))\nprovide(dataContextKey, {\n store,\n sourceNames: () => sourceNames.value,\n filters: () => values.value,\n emitted: (id) => emittedByWidget.value.get(id) ?? EMPTY_SET,\n linked: (id) => linksByWidget.value.get(id) ?? NO_LINKS,\n setFilter,\n})\n\n// ---------------------------------------------------------------------------\n// Keyboard and clipboard\n\nconst CLIPBOARD_KIND = 'dou-dashboard/widget'\n\nfunction isTyping(target: EventTarget | null) {\n const el = target as HTMLElement | null\n if (!el?.tagName) return false\n return (\n el.isContentEditable ||\n el.tagName === 'TEXTAREA' ||\n el.tagName === 'SELECT' ||\n (el.tagName === 'INPUT' &&\n !['checkbox', 'radio', 'button', 'range', 'color'].includes((el as HTMLInputElement).type))\n )\n}\n\n/** The widget an element is in, such as the one holding the focus. */\nfunction widgetHolding(target: EventTarget | null) {\n const el = (target as HTMLElement | null)?.closest?.<HTMLElement>('[data-grid-id]')\n return el && el.closest('.dou-dashboard') === root.value ? el.dataset.gridId : undefined\n}\n\n/** The widget whose item itself has focus (not a control inside it). */\nfunction focusedId(target: EventTarget | null) {\n const el = target as HTMLElement | null\n return el?.dataset?.gridId && el.closest('.dou-dashboard') === root.value\n ? el.dataset.gridId\n : undefined\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (event.defaultPrevented || isTyping(event.target)) return\n // anywhere in a widget, also while viewing: its discussions\n if (matchesHotkey(event, 'mod+alt+m') && comments.enabled.value) {\n const id = widgetHolding(event.target)\n if (id && comments.start(id)) event.preventDefault()\n return\n }\n if (!props.editable) return\n if (matchesHotkey(event, 'mod+z')) {\n event.preventDefault()\n undo()\n return\n }\n if (matchesHotkey(event, 'mod+shift+z') || matchesHotkey(event, 'mod+y')) {\n event.preventDefault()\n redo()\n return\n }\n const id = focusedId(event.target)\n if (!id || dragging.value) return\n if (event.key === 'Delete' || event.key === 'Backspace') {\n event.preventDefault()\n removeWidget(id)\n } else if (matchesHotkey(event, 'mod+d')) {\n event.preventDefault()\n duplicateWidget(id)\n }\n}\n\nfunction onCopy(event: ClipboardEvent, cut = false) {\n if (isTyping(event.target)) return\n const id = focusedId(event.target)\n const widget = id && widgetMap.value.get(id)\n if (!widget || !event.clipboardData) return\n event.clipboardData.setData('text/plain', JSON.stringify({ kind: CLIPBOARD_KIND, widget }))\n event.preventDefault()\n if (cut && props.editable) removeWidget(widget.id)\n}\n\nfunction onPaste(event: ClipboardEvent) {\n if (!props.editable || isTyping(event.target)) return\n let data: { kind?: string; widget?: DashboardWidget } | undefined\n try {\n data = JSON.parse(event.clipboardData?.getData('text/plain') ?? '')\n } catch {\n return\n }\n const widget = data?.kind === CLIPBOARD_KIND ? data.widget : undefined\n if (!widget?.type || !typeMap.value.has(widget.type)) return\n event.preventDefault()\n const id = focusedId(event.target)\n addCopy(widget, id ? items.value.find((item) => item.id === id) : undefined)\n}\n\n// ---------------------------------------------------------------------------\n// Export and print\n\n/** Every widget drawn in full, not only those near the view. */\nconst showAll = ref(false)\nconst nextFrame = () => new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))\n\n/** Draws every widget (unless `all` is false) and waits for their sources (at most `timeout` ms) and one more frame. */\nasync function settle(timeout = 5000, all = true) {\n if (all) showAll.value = true\n await nextTick()\n const start = performance.now()\n await nextFrame()\n while (store.busy() && performance.now() - start < timeout) await nextFrame()\n await nextFrame()\n await nextFrame()\n}\n\n/** The dashboard as it is shown, every widget drawn, as a PNG image. */\nasync function exportPNG(options?: DashboardImageOptions) {\n await settle()\n const el = root.value!\n // the controls are left out; the copy is made before the class goes\n el.classList.add('is-exporting')\n try {\n return elementToPNG(el, options)\n } finally {\n el.classList.remove('is-exporting')\n }\n}\n\n/** Draws every widget, waits for their data, and opens the browser's print dialog. */\nasync function print() {\n await settle()\n window.print()\n}\n\n// printing from the browser's menu: draw what is far from the view, as far as there is time\nfunction onBeforePrint() {\n showAll.value = true\n}\nonMounted(() => window.addEventListener('beforeprint', onBeforePrint))\nonBeforeUnmount(() => window.removeEventListener('beforeprint', onBeforePrint))\n\n// ---------------------------------------------------------------------------\n// Announcements\n\nconst live = ref('')\nfunction say(text: string) {\n live.value = ''\n requestAnimationFrame(() => (live.value = text))\n}\n\nconst breakpointName = shallowRef(main.value.name)\nfunction onBreakpoint(name: string) {\n breakpointName.value = name\n emit('breakpointChange', name)\n}\n\nconst minHeight = computed(() => {\n const gap = Array.isArray(props.gap) ? props.gap[1] : props.gap\n return `${props.rowHeight * 3 + gap * 2}px`\n})\n\ndefineExpose<DashboardExpose>({\n transaction,\n dispatch,\n undo,\n redo,\n get canUndo() {\n return canUndo.value\n },\n get canRedo() {\n return canRedo.value\n },\n addWidget,\n removeWidget,\n comment: (id = widgetHolding(document.activeElement)) => !!id && comments.start(id),\n getCommentAnchors: comments.anchors,\n duplicateWidget,\n focusWidget,\n openSettings,\n openFullscreen,\n startAdd,\n get types() {\n return props.widgets\n },\n get breakpoint() {\n return grid.value?.breakpoint ?? breakpointName.value\n },\n get editable() {\n return props.editable\n },\n get document() {\n return model.value\n },\n get filters() {\n return values.value\n },\n get linkedFilters() {\n return [...links.value.values()]\n },\n setFilter: (key, value, options) => setFilter(undefined, key, value, options),\n clearFilters,\n refresh: (source) => store.reload(source),\n exportPNG,\n exportWidget: exportWidget as DashboardExpose['exportWidget'],\n saveWidget: saveWidget as DashboardExpose['saveWidget'],\n print,\n})\n</script>\n\n<template>\n <div\n ref=\"root\"\n :class=\"['dou-dashboard', editable && 'is-editable']\"\n role=\"region\"\n :aria-label=\"label || messages.dashboard\"\n tabindex=\"-1\"\n @keydown=\"onKeydown\"\n @copy=\"onCopy($event)\"\n @cut=\"onCopy($event, true)\"\n @paste=\"onPaste\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <GridLayout\n ref=\"grid\"\n :model-value=\"items\"\n :layouts=\"layouts\"\n :columns=\"columns\"\n :breakpoints=\"breakpoints\"\n :row-height=\"rowHeight\"\n :gap=\"gap\"\n :compact=\"compact\"\n :editable=\"editable\"\n :handle=\"true\"\n :item-label=\"labelOf\"\n :messages=\"messages\"\n :style=\"editable && !model.widgets.length ? { minHeight } : undefined\"\n @update:model-value=\"(list) => gather({ items: list })\"\n @update:layouts=\"(next) => gather({ layouts: next })\"\n @drop=\"onDrop\"\n @drag-start=\"onDragStart\"\n @drag-end=\"onDragEnd\"\n @breakpoint-change=\"onBreakpoint\"\n >\n <template #item=\"{ item }\">\n <WidgetFrame :id=\"item.id\" />\n </template>\n </GridLayout>\n <div v-if=\"editable && !model.widgets.length\" class=\"dou-dashboard__empty\">\n <DouEmpty size=\"sm\" :title=\"messages.emptyTitle\" :description=\"messages.emptyHint\">\n <template #icon><LayoutGridPlusIcon /></template>\n </DouEmpty>\n </div>\n <div class=\"dou-dashboard__live\" aria-live=\"polite\" aria-atomic=\"true\">{{ live }}</div>\n <!-- in fullscreen the card goes in the dialog, which keeps the focus to itself -->\n <CommentCard\n v-if=\"comments.enabled.value && !fullscreenWidget\"\n :comments=\"comments\"\n :messages=\"messages\"\n :button-of=\"buttonOf\"\n :place-of=\"cardSpotOf\"\n />\n <DouDrawer\n :open=\"!!settingsWidget\"\n :title=\"\n settingsWidget ? format(messages.settingsTitle, { title: titleOf(settingsWidget) }) : ''\n \"\n :size=\"360\"\n @update:open=\"(open) => !open && (settingsId = undefined)\"\n @closed=\"restoreFocus\"\n >\n <div v-if=\"settingsWidget\" class=\"dou-dashboard__settings\">\n <label class=\"dou-dashboard__field\">\n <span class=\"dou-dashboard__field-label\">{{ messages.titleField }}</span>\n <DouInput\n :model-value=\"settingsWidget.title ?? ''\"\n :placeholder=\"typeOf(settingsWidget)?.label ?? settingsWidget.type\"\n @update:model-value=\"\n (value) =>\n run(\n [\n {\n type: 'update',\n id: settingsWidget!.id,\n patch: { title: value || undefined },\n },\n ],\n { origin: 'settings', group: `title:${settingsWidget!.id}` },\n )\n \"\n />\n </label>\n <WidgetSettings\n v-if=\"typeOf(settingsWidget)?.settings\"\n :widget=\"settingsWidget\"\n :type=\"typeOf(settingsWidget)!\"\n :set-props=\"setProps\"\n @update:props=\"\n (value) =>\n run([{ type: 'update', id: settingsWidget!.id, patch: { props: value } }], {\n origin: 'settings',\n group: `props:${settingsWidget!.id}`,\n })\n \"\n />\n </div>\n </DouDrawer>\n <DouDialog\n :open=\"!!fullscreenWidget\"\n :title=\"fullscreenWidget ? titleOf(fullscreenWidget) : ''\"\n fullscreen\n @update:open=\"(open) => !open && (fullscreenId = undefined)\"\n @closed=\"restoreFocus\"\n @keydown=\"onFullscreenKeydown\"\n >\n <div v-if=\"fullscreenWidget\" ref=\"fullscreenBody\" class=\"dou-dashboard__fullscreen\">\n <div v-if=\"comments.enabled.value\" class=\"dou-dashboard__fullscreen-bar\">\n <CommentButton\n :id=\"fullscreenWidget.id\"\n :comments=\"comments\"\n :messages=\"messages\"\n tooltip-placement=\"left\"\n />\n </div>\n <WidgetBody\n class=\"is-fullscreen\"\n :widget=\"fullscreenWidget\"\n :type=\"typeOf(fullscreenWidget)\"\n :editing=\"false\"\n fullscreen\n :messages=\"messages\"\n :set-props=\"setProps\"\n />\n <CommentCard\n v-if=\"comments.enabled.value\"\n :comments=\"comments\"\n :messages=\"messages\"\n :button-of=\"buttonOf\"\n :place-of=\"cardSpotOf\"\n />\n </div>\n </DouDialog>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"frame-context.js","names":[],"sources":["../../src/dashboard/frame-context.ts"],"sourcesContent":["import type { SheetWorkbook } from '@dou-ui/sheet/core'\nimport type { Component, InjectionKey } from 'vue'\nimport type { DashboardPeer } from '../core/collaboration'\nimport type { DashboardWidget } from '../core/types'\nimport type { DashboardLinkedFilter } from '../data/types'\nimport type { DashboardMessages } from '../locale'\nimport type { DashboardWidgetType } from '../widget/define'\n\nexport type WidgetAction = 'settings' | 'fullscreen' | 'duplicate' | 'remove'\n\n/** An exporter as the export menu lists it. */\nexport interface FrameExporter {\n name: string\n label: string\n icon?: Component\n}\n\n/**\n * What a widget's frame reads from its dashboard. The frame looks its widget\n * up by id in a computed of its own, so a change to one widget draws only\n * that widget's frame again, not every frame on the grid.\n */\nexport interface FrameContext {\n widget: (id: string) => DashboardWidget | undefined\n type: (widget: DashboardWidget) => DashboardWidgetType<any> | undefined\n title: (widget: DashboardWidget) => string\n editing: () => boolean\n messages: () => DashboardMessages\n /** Whether a frame mounting now is drawn in full at once. */\n eager: (id: string) => boolean\n /** Whether every widget is drawn in full now, to export or print the dashboard. */\n all: () => boolean\n setProps: (id: string, patch: Record<string, unknown>, options?: { group?: string }) => void\n action: (id: string, action: WidgetAction) => void\n rename: (id: string, title: string) => void\n /** The filters a widget set, shown in its title bar. */\n linked: (id: string) => DashboardLinkedFilter[]\n clearFilter: (key: string) => void\n /** The others at a widget, when editing together. */\n peers: (id: string) => readonly DashboardPeer[]\n /** How a widget gives its content as a workbook; returns what undoes it. */\n setWorkbook: (id: string, get: () => SheetWorkbook | undefined) => () => void\n /** The exporters a widget's menu lists: none unless it gives a workbook. */\n exporters: (id: string) => FrameExporter[]\n /** Writes a widget's content with an exporter, by name, and downloads the file. */\n exportTo: (id: string, exporter: string) => void\n /** Tells whether a widget is drawn in full, not only its title. */\n setDrawn: (id: string, drawn: boolean) => void\n /** Whether a widget's content is being exported now. */\n exporting: (id: string) => boolean\n /** Why the last export from a widget's menu failed. */\n exportError: (id: string) => string | undefined\n clearExportError: (id: string) => void\n}\n\nexport const frameContextKey: InjectionKey<FrameContext> = Symbol('dou-dashboard-frame')\n"],"mappings":";AAuDA,IAAa,kBAA8C,OAAO,qBAAqB"}
1
+ {"version":3,"file":"frame-context.js","names":[],"sources":["../../src/dashboard/frame-context.ts"],"sourcesContent":["import type { SheetWorkbook } from '@dou-ui/sheet/core'\nimport type { Component, InjectionKey } from 'vue'\nimport type { DashboardPeer } from '../core/collaboration'\nimport type { DashboardComments } from './comments'\nimport type { DashboardWidget } from '../core/types'\nimport type { DashboardLinkedFilter } from '../data/types'\nimport type { DashboardMessages } from '../locale'\nimport type { DashboardWidgetType } from '../widget/define'\n\nexport type WidgetAction = 'settings' | 'fullscreen' | 'duplicate' | 'remove'\n\n/** An exporter as the export menu lists it. */\nexport interface FrameExporter {\n name: string\n label: string\n icon?: Component\n}\n\n/**\n * What a widget's frame reads from its dashboard. The frame looks its widget\n * up by id in a computed of its own, so a change to one widget draws only\n * that widget's frame again, not every frame on the grid.\n */\nexport interface FrameContext {\n comments: DashboardComments\n widget: (id: string) => DashboardWidget | undefined\n type: (widget: DashboardWidget) => DashboardWidgetType<any> | undefined\n title: (widget: DashboardWidget) => string\n editing: () => boolean\n messages: () => DashboardMessages\n /** Whether a frame mounting now is drawn in full at once. */\n eager: (id: string) => boolean\n /** Whether every widget is drawn in full now, to export or print the dashboard. */\n all: () => boolean\n setProps: (id: string, patch: Record<string, unknown>, options?: { group?: string }) => void\n action: (id: string, action: WidgetAction) => void\n rename: (id: string, title: string) => void\n /** The filters a widget set, shown in its title bar. */\n linked: (id: string) => DashboardLinkedFilter[]\n clearFilter: (key: string) => void\n /** The others at a widget, when editing together. */\n peers: (id: string) => readonly DashboardPeer[]\n /** How a widget gives its content as a workbook; returns what undoes it. */\n setWorkbook: (id: string, get: () => SheetWorkbook | undefined) => () => void\n /** The exporters a widget's menu lists: none unless it gives a workbook. */\n exporters: (id: string) => FrameExporter[]\n /** Writes a widget's content with an exporter, by name, and downloads the file. */\n exportTo: (id: string, exporter: string) => void\n /** Tells whether a widget is drawn in full, not only its title. */\n setDrawn: (id: string, drawn: boolean) => void\n /** Whether a widget's content is being exported now. */\n exporting: (id: string) => boolean\n /** Why the last export from a widget's menu failed. */\n exportError: (id: string) => string | undefined\n clearExportError: (id: string) => void\n}\n\nexport const frameContextKey: InjectionKey<FrameContext> = Symbol('dou-dashboard-frame')\n"],"mappings":";AAyDA,IAAa,kBAA8C,OAAO,qBAAqB"}
@@ -1 +1 @@
1
- {"version":3,"file":"widget-frame.js","names":["_sfc_main"],"sources":["../../src/dashboard/widget-frame.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DownloadIcon, MaximizeIcon, MoreHorizontalIcon } from '@dou-ui/icons'\nimport {\n DouAlert,\n DouButton,\n DouDropdown,\n DouDropdownItem,\n DouDropdownSub,\n DouEditable,\n DouTag,\n DouTooltip,\n} from 'dou-ui'\nimport type { DropdownValue } from 'dou-ui'\nimport { computed, inject, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport GridLayoutHandle from '../grid/grid-handle.vue'\nimport { format } from '../locale'\nimport { frameContextKey } from './frame-context'\nimport type { WidgetAction } from './frame-context'\nimport { observersKey } from './observers'\nimport WidgetBody from './widget-body.vue'\n\ndefineOptions({ name: 'DouDashboardWidget' })\n\nconst props = defineProps<{ id: string }>()\n\nconst frame = inject(frameContextKey)!\nconst widget = computed(() => frame.widget(props.id))\nconst type = computed(() => widget.value && frame.type(widget.value))\nconst title = computed(() => (widget.value ? frame.title(widget.value) : ''))\nconst editing = computed(() => frame.editing())\nconst messages = computed(() => frame.messages())\n/** The filters this widget set, each with a button to clear it. */\nconst linked = computed(() => frame.linked(props.id))\n/** All of them in one tag (a pivot table's click sets one per field), cleared together. */\nconst linkLabel = computed(() => linked.value.map((link) => link.label).join(' / '))\nfunction clearLinks() {\n for (const link of linked.value) frame.clearFilter(link.key)\n}\n\n/** Others at this widget, when editing together: an outline in the first one's color and their names. */\nconst peers = computed(() => frame.peers(props.id))\nconst peerText = (peer: { name: string; action: string }) => {\n const m = messages.value\n const text =\n peer.action === 'move'\n ? m.peerMoving\n : peer.action === 'resize'\n ? m.peerResizing\n : peer.action === 'settings'\n ? m.peerSettings\n : '{name}'\n return format(text, { name: peer.name })\n}\n\nconst renaming = ref(false)\n\n// Widgets far out of view show only their title until they come near: with\n// hundreds of widgets, their contents and controls are most of the mounting.\nconst root = ref<HTMLElement>()\nconst active = ref(frame.eager(props.id))\nconst observers = inject(observersKey)\nlet stop: (() => void) | undefined\nonMounted(() => {\n if (active.value || !observers) {\n active.value = true\n return\n }\n stop = observers.near(root.value!, () => {\n active.value = true\n stop?.()\n })\n})\nonBeforeUnmount(() => stop?.())\n// the dashboard draws everything for an export only when this widget isn't drawn yet\nwatch(active, (drawn) => frame.setDrawn(props.id, drawn), { immediate: true })\nonBeforeUnmount(() => frame.setDrawn(props.id, false))\n// drawn in full to export or print the dashboard, and kept that way\nwatch(\n () => frame.all(),\n (all) => {\n if (!all || active.value) return\n active.value = true\n stop?.()\n },\n { immediate: true },\n)\nconst canFullscreen = computed(() => type.value?.fullscreen !== false)\n\nconst emitAction = (action: WidgetAction) => frame.action(props.id, action)\n\n/** The file types this widget's content can be exported as; none unless it gives a workbook. */\nconst exporters = computed(() => frame.exporters(props.id))\nconst exportError = computed(() => frame.exportError(props.id))\nconst exporting = computed(() => frame.exporting(props.id))\nconst EXPORT = 'export:'\nconst exportOpen = ref(false)\n\nfunction onSelect(value: DropdownValue | undefined) {\n if (typeof value !== 'string') return\n if (value.startsWith(EXPORT)) frame.exportTo(props.id, value.slice(EXPORT.length))\n else emitAction(value as WidgetAction)\n}\n</script>\n\n<template>\n <!-- outside the frame, which cuts off what overflows it -->\n <div v-if=\"widget && peers.length\" class=\"dou-dashboard__peers\" aria-hidden=\"true\">\n <span\n v-for=\"peer in peers\"\n :key=\"`${peer.client}:${peer.action}`\"\n :class=\"['dou-dashboard__peer', `is-${peer.action}`]\"\n :style=\"{ '--dou-dashboard-peer-color': peer.color }\"\n >\n {{ peerText(peer) }}\n </span>\n </div>\n <div\n v-if=\"widget\"\n ref=\"root\"\n :class=\"['dou-dashboard__widget', peers.length && 'has-peers']\"\n :style=\"peers.length ? { '--dou-dashboard-peer-color': peers[0]!.color } : undefined\"\n >\n <template v-if=\"!active\">\n <div class=\"dou-dashboard__header\">\n <div class=\"dou-dashboard__title\">{{ title }}</div>\n </div>\n <div class=\"dou-dashboard__body\" />\n </template>\n <component\n v-else\n :is=\"editing ? GridLayoutHandle : 'div'\"\n :as=\"editing ? 'header' : undefined\"\n class=\"dou-dashboard__header\"\n >\n <DouEditable\n v-if=\"editing\"\n v-model:editing=\"renaming\"\n class=\"dou-dashboard__title\"\n :model-value=\"title\"\n trigger=\"dblclick\"\n select-on-edit\n :aria-label=\"messages.titleField\"\n :data-dou-nodrag=\"renaming ? '' : undefined\"\n @submit=\"(value) => frame.rename(id, value)\"\n />\n <div v-else class=\"dou-dashboard__title\">{{ title }}</div>\n <div v-if=\"linked.length\" class=\"dou-dashboard__links\" data-dou-nodrag>\n <DouTag\n size=\"sm\"\n closable\n :close-label=\"format(messages.clearFilter, { value: linkLabel })\"\n @close=\"clearLinks\"\n >\n {{ format(messages.filteredBy, { value: linkLabel }) }}\n </DouTag>\n </div>\n <div class=\"dou-dashboard__actions\" data-dou-nodrag>\n <DouDropdown v-if=\"editing\" placement=\"bottom-end\" @select=\"onSelect\">\n <DouButton size=\"sm\" variant=\"ghost\" :aria-label=\"messages.widgetMenu\">\n <MoreHorizontalIcon />\n </DouButton>\n <template #menu>\n <DouDropdownItem value=\"settings\">{{ messages.settings }}</DouDropdownItem>\n <DouDropdownItem v-if=\"canFullscreen\" value=\"fullscreen\">\n {{ messages.fullscreen }}\n </DouDropdownItem>\n <DouDropdownSub v-if=\"exporters.length\" :title=\"messages.export\">\n <DouDropdownItem\n v-for=\"exporter in exporters\"\n :key=\"exporter.name\"\n :value=\"EXPORT + exporter.name\"\n :disabled=\"exporting\"\n >\n <template v-if=\"exporter.icon\" #prefix><component :is=\"exporter.icon\" /></template>\n {{ exporter.label }}\n </DouDropdownItem>\n </DouDropdownSub>\n <DouDropdownItem value=\"duplicate\" shortcut=\"mod+d\">\n {{ messages.duplicate }}\n </DouDropdownItem>\n <DouDropdownItem value=\"remove\" tone=\"danger\" shortcut=\"delete\" divided>\n {{ messages.remove }}\n </DouDropdownItem>\n </template>\n </DouDropdown>\n <DouTooltip v-if=\"!editing && exporters.length\" :content=\"messages.export\">\n <DouDropdown v-model:open=\"exportOpen\" placement=\"bottom-end\" @select=\"onSelect\">\n <DouButton\n size=\"sm\"\n variant=\"ghost\"\n :aria-label=\"messages.export\"\n :loading=\"exporting\"\n :disabled=\"exporting\"\n >\n <DownloadIcon />\n </DouButton>\n <template #menu>\n <DouDropdownItem\n v-for=\"exporter in exporters\"\n :key=\"exporter.name\"\n :value=\"EXPORT + exporter.name\"\n >\n <template v-if=\"exporter.icon\" #prefix><component :is=\"exporter.icon\" /></template>\n {{ exporter.label }}\n </DouDropdownItem>\n </template>\n </DouDropdown>\n </DouTooltip>\n <DouTooltip v-if=\"!editing && canFullscreen\" :content=\"messages.fullscreen\">\n <DouButton\n size=\"sm\"\n variant=\"ghost\"\n :aria-label=\"messages.fullscreen\"\n @click=\"emitAction('fullscreen')\"\n >\n <MaximizeIcon />\n </DouButton>\n </DouTooltip>\n </div>\n </component>\n <div v-if=\"exportError\" class=\"dou-dashboard__export-error\" data-dou-nodrag>\n <DouAlert tone=\"danger\" closable @close=\"frame.clearExportError(id)\">\n {{ exportError }}\n </DouAlert>\n </div>\n <WidgetBody\n v-if=\"active\"\n :widget=\"widget\"\n :type=\"type\"\n :editing=\"editing\"\n :messages=\"messages\"\n :set-props=\"frame.setProps\"\n :set-workbook=\"frame.setWorkbook\"\n />\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"widget-frame.js","names":["_sfc_main"],"sources":["../../src/dashboard/widget-frame.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DownloadIcon, MaximizeIcon, MoreHorizontalIcon } from '@dou-ui/icons'\nimport {\n DouAlert,\n DouButton,\n DouDropdown,\n DouDropdownItem,\n DouDropdownSub,\n DouEditable,\n DouTag,\n DouTooltip,\n} from 'dou-ui'\nimport type { DropdownValue } from 'dou-ui'\nimport { computed, inject, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport GridLayoutHandle from '../grid/grid-handle.vue'\nimport { format } from '../locale'\nimport { frameContextKey } from './frame-context'\nimport type { WidgetAction } from './frame-context'\nimport { observersKey } from './observers'\nimport CommentButton from './comment-button.vue'\nimport WidgetBody from './widget-body.vue'\n\ndefineOptions({ name: 'DouDashboardWidget' })\n\nconst props = defineProps<{ id: string }>()\n\nconst frame = inject(frameContextKey)!\nconst widget = computed(() => frame.widget(props.id))\nconst type = computed(() => widget.value && frame.type(widget.value))\nconst title = computed(() => (widget.value ? frame.title(widget.value) : ''))\nconst editing = computed(() => frame.editing())\nconst messages = computed(() => frame.messages())\n/** The filters this widget set, each with a button to clear it. */\nconst linked = computed(() => frame.linked(props.id))\n/** All of them in one tag (a pivot table's click sets one per field), cleared together. */\nconst linkLabel = computed(() => linked.value.map((link) => link.label).join(' / '))\nfunction clearLinks() {\n for (const link of linked.value) frame.clearFilter(link.key)\n}\n\n/** Others at this widget, when editing together: an outline in the first one's color and their names. */\nconst peers = computed(() => frame.peers(props.id))\nconst peerText = (peer: { name: string; action: string }) => {\n const m = messages.value\n const text =\n peer.action === 'move'\n ? m.peerMoving\n : peer.action === 'resize'\n ? m.peerResizing\n : peer.action === 'settings'\n ? m.peerSettings\n : '{name}'\n return format(text, { name: peer.name })\n}\n\nconst renaming = ref(false)\n\n// Widgets far out of view show only their title until they come near: with\n// hundreds of widgets, their contents and controls are most of the mounting.\nconst root = ref<HTMLElement>()\nconst active = ref(frame.eager(props.id))\nconst observers = inject(observersKey)\nlet stop: (() => void) | undefined\nonMounted(() => {\n if (active.value || !observers) {\n active.value = true\n return\n }\n stop = observers.near(root.value!, () => {\n active.value = true\n stop?.()\n })\n})\nonBeforeUnmount(() => stop?.())\n// the dashboard draws everything for an export only when this widget isn't drawn yet\nwatch(active, (drawn) => frame.setDrawn(props.id, drawn), { immediate: true })\nonBeforeUnmount(() => frame.setDrawn(props.id, false))\n// drawn in full to export or print the dashboard, and kept that way\nwatch(\n () => frame.all(),\n (all) => {\n if (!all || active.value) return\n active.value = true\n stop?.()\n },\n { immediate: true },\n)\nconst canFullscreen = computed(() => type.value?.fullscreen !== false)\n\nconst emitAction = (action: WidgetAction) => frame.action(props.id, action)\n\n/** The file types this widget's content can be exported as; none unless it gives a workbook. */\nconst exporters = computed(() => frame.exporters(props.id))\nconst exportError = computed(() => frame.exportError(props.id))\nconst exporting = computed(() => frame.exporting(props.id))\nconst EXPORT = 'export:'\nconst exportOpen = ref(false)\n\nfunction onSelect(value: DropdownValue | undefined) {\n if (typeof value !== 'string') return\n if (value.startsWith(EXPORT)) frame.exportTo(props.id, value.slice(EXPORT.length))\n else emitAction(value as WidgetAction)\n}\n</script>\n\n<template>\n <!-- outside the frame, which cuts off what overflows it -->\n <div v-if=\"widget && peers.length\" class=\"dou-dashboard__peers\" aria-hidden=\"true\">\n <span\n v-for=\"peer in peers\"\n :key=\"`${peer.client}:${peer.action}`\"\n :class=\"['dou-dashboard__peer', `is-${peer.action}`]\"\n :style=\"{ '--dou-dashboard-peer-color': peer.color }\"\n >\n {{ peerText(peer) }}\n </span>\n </div>\n <div\n v-if=\"widget\"\n ref=\"root\"\n :class=\"['dou-dashboard__widget', peers.length && 'has-peers']\"\n :style=\"peers.length ? { '--dou-dashboard-peer-color': peers[0]!.color } : undefined\"\n >\n <template v-if=\"!active\">\n <div class=\"dou-dashboard__header\">\n <div class=\"dou-dashboard__title\">{{ title }}</div>\n </div>\n <div class=\"dou-dashboard__body\" />\n </template>\n <component\n v-else\n :is=\"editing ? GridLayoutHandle : 'div'\"\n :as=\"editing ? 'header' : undefined\"\n class=\"dou-dashboard__header\"\n >\n <DouEditable\n v-if=\"editing\"\n v-model:editing=\"renaming\"\n class=\"dou-dashboard__title\"\n :model-value=\"title\"\n trigger=\"dblclick\"\n select-on-edit\n :aria-label=\"messages.titleField\"\n :data-dou-nodrag=\"renaming ? '' : undefined\"\n @submit=\"(value) => frame.rename(id, value)\"\n />\n <div v-else class=\"dou-dashboard__title\">{{ title }}</div>\n <div v-if=\"linked.length\" class=\"dou-dashboard__links\" data-dou-nodrag>\n <DouTag\n size=\"sm\"\n closable\n :close-label=\"format(messages.clearFilter, { value: linkLabel })\"\n @close=\"clearLinks\"\n >\n {{ format(messages.filteredBy, { value: linkLabel }) }}\n </DouTag>\n </div>\n <div class=\"dou-dashboard__actions\" data-dou-nodrag>\n <CommentButton :id=\"id\" :comments=\"frame.comments\" :messages=\"messages\" />\n <DouDropdown v-if=\"editing\" placement=\"bottom-end\" @select=\"onSelect\">\n <DouButton size=\"sm\" variant=\"ghost\" :aria-label=\"messages.widgetMenu\">\n <MoreHorizontalIcon />\n </DouButton>\n <template #menu>\n <DouDropdownItem value=\"settings\">{{ messages.settings }}</DouDropdownItem>\n <DouDropdownItem v-if=\"canFullscreen\" value=\"fullscreen\">\n {{ messages.fullscreen }}\n </DouDropdownItem>\n <DouDropdownSub v-if=\"exporters.length\" :title=\"messages.export\">\n <DouDropdownItem\n v-for=\"exporter in exporters\"\n :key=\"exporter.name\"\n :value=\"EXPORT + exporter.name\"\n :disabled=\"exporting\"\n >\n <template v-if=\"exporter.icon\" #prefix><component :is=\"exporter.icon\" /></template>\n {{ exporter.label }}\n </DouDropdownItem>\n </DouDropdownSub>\n <DouDropdownItem value=\"duplicate\" shortcut=\"mod+d\">\n {{ messages.duplicate }}\n </DouDropdownItem>\n <DouDropdownItem value=\"remove\" tone=\"danger\" shortcut=\"delete\" divided>\n {{ messages.remove }}\n </DouDropdownItem>\n </template>\n </DouDropdown>\n <DouTooltip v-if=\"!editing && exporters.length\" :content=\"messages.export\">\n <DouDropdown v-model:open=\"exportOpen\" placement=\"bottom-end\" @select=\"onSelect\">\n <DouButton\n size=\"sm\"\n variant=\"ghost\"\n :aria-label=\"messages.export\"\n :loading=\"exporting\"\n :disabled=\"exporting\"\n >\n <DownloadIcon />\n </DouButton>\n <template #menu>\n <DouDropdownItem\n v-for=\"exporter in exporters\"\n :key=\"exporter.name\"\n :value=\"EXPORT + exporter.name\"\n >\n <template v-if=\"exporter.icon\" #prefix><component :is=\"exporter.icon\" /></template>\n {{ exporter.label }}\n </DouDropdownItem>\n </template>\n </DouDropdown>\n </DouTooltip>\n <DouTooltip v-if=\"!editing && canFullscreen\" :content=\"messages.fullscreen\">\n <DouButton\n size=\"sm\"\n variant=\"ghost\"\n :aria-label=\"messages.fullscreen\"\n @click=\"emitAction('fullscreen')\"\n >\n <MaximizeIcon />\n </DouButton>\n </DouTooltip>\n </div>\n </component>\n <div v-if=\"exportError\" class=\"dou-dashboard__export-error\" data-dou-nodrag>\n <DouAlert tone=\"danger\" closable @close=\"frame.clearExportError(id)\">\n {{ exportError }}\n </DouAlert>\n </div>\n <WidgetBody\n v-if=\"active\"\n :widget=\"widget\"\n :type=\"type\"\n :editing=\"editing\"\n :messages=\"messages\"\n :set-props=\"frame.setProps\"\n :set-workbook=\"frame.setWorkbook\"\n />\n </div>\n</template>\n"],"mappings":""}
@@ -3,6 +3,7 @@ import grid_handle_default from "../grid/grid-handle.js";
3
3
  import { observersKey } from "./observers.js";
4
4
  import widget_body_default from "./widget-body.js";
5
5
  import { frameContextKey } from "./frame-context.js";
6
+ import comment_button_default from "./comment-button.js";
6
7
  import { DouAlert, DouButton, DouDropdown, DouDropdownItem, DouDropdownSub, DouEditable, DouTag, DouTooltip } from "dou-ui";
7
8
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, inject, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, ref, renderList, resolveDynamicComponent, toDisplayString, unref, watch, withCtx } from "vue";
8
9
  import { DownloadIcon, MaximizeIcon, MoreHorizontalIcon } from "@dou-ui/icons";
@@ -141,6 +142,15 @@ var widget_frame_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ def
141
142
  _: 1
142
143
  }, 8, ["close-label"])])) : createCommentVNode("", true),
143
144
  createElementVNode("div", _hoisted_6, [
145
+ createVNode(comment_button_default, {
146
+ id: __props.id,
147
+ comments: unref(frame).comments,
148
+ messages: messages.value
149
+ }, null, 8, [
150
+ "id",
151
+ "comments",
152
+ "messages"
153
+ ]),
144
154
  editing.value ? (openBlock(), createBlock(unref(DouDropdown), {
145
155
  key: 0,
146
156
  placement: "bottom-end",
@@ -1 +1 @@
1
- {"version":3,"file":"widget-frame.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_Fragment","_renderList","_normalizeClass","_normalizeStyle","_toDisplayString","_createCommentVNode","_createElementVNode","_createBlock","_resolveDynamicComponent","GridLayoutHandle","_withCtx","_unref","_createVNode","_createTextVNode","_createSlots","WidgetBody"],"sources":["../../src/dashboard/widget-frame.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DownloadIcon, MaximizeIcon, MoreHorizontalIcon } from '@dou-ui/icons'\nimport {\n DouAlert,\n DouButton,\n DouDropdown,\n DouDropdownItem,\n DouDropdownSub,\n DouEditable,\n DouTag,\n DouTooltip,\n} from 'dou-ui'\nimport type { DropdownValue } from 'dou-ui'\nimport { computed, inject, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport GridLayoutHandle from '../grid/grid-handle.vue'\nimport { format } from '../locale'\nimport { frameContextKey } from './frame-context'\nimport type { WidgetAction } from './frame-context'\nimport { observersKey } from './observers'\nimport WidgetBody from './widget-body.vue'\n\ndefineOptions({ name: 'DouDashboardWidget' })\n\nconst props = defineProps<{ id: string }>()\n\nconst frame = inject(frameContextKey)!\nconst widget = computed(() => frame.widget(props.id))\nconst type = computed(() => widget.value && frame.type(widget.value))\nconst title = computed(() => (widget.value ? frame.title(widget.value) : ''))\nconst editing = computed(() => frame.editing())\nconst messages = computed(() => frame.messages())\n/** The filters this widget set, each with a button to clear it. */\nconst linked = computed(() => frame.linked(props.id))\n/** All of them in one tag (a pivot table's click sets one per field), cleared together. */\nconst linkLabel = computed(() => linked.value.map((link) => link.label).join(' / '))\nfunction clearLinks() {\n for (const link of linked.value) frame.clearFilter(link.key)\n}\n\n/** Others at this widget, when editing together: an outline in the first one's color and their names. */\nconst peers = computed(() => frame.peers(props.id))\nconst peerText = (peer: { name: string; action: string }) => {\n const m = messages.value\n const text =\n peer.action === 'move'\n ? m.peerMoving\n : peer.action === 'resize'\n ? m.peerResizing\n : peer.action === 'settings'\n ? m.peerSettings\n : '{name}'\n return format(text, { name: peer.name })\n}\n\nconst renaming = ref(false)\n\n// Widgets far out of view show only their title until they come near: with\n// hundreds of widgets, their contents and controls are most of the mounting.\nconst root = ref<HTMLElement>()\nconst active = ref(frame.eager(props.id))\nconst observers = inject(observersKey)\nlet stop: (() => void) | undefined\nonMounted(() => {\n if (active.value || !observers) {\n active.value = true\n return\n }\n stop = observers.near(root.value!, () => {\n active.value = true\n stop?.()\n })\n})\nonBeforeUnmount(() => stop?.())\n// the dashboard draws everything for an export only when this widget isn't drawn yet\nwatch(active, (drawn) => frame.setDrawn(props.id, drawn), { immediate: true })\nonBeforeUnmount(() => frame.setDrawn(props.id, false))\n// drawn in full to export or print the dashboard, and kept that way\nwatch(\n () => frame.all(),\n (all) => {\n if (!all || active.value) return\n active.value = true\n stop?.()\n },\n { immediate: true },\n)\nconst canFullscreen = computed(() => type.value?.fullscreen !== false)\n\nconst emitAction = (action: WidgetAction) => frame.action(props.id, action)\n\n/** The file types this widget's content can be exported as; none unless it gives a workbook. */\nconst exporters = computed(() => frame.exporters(props.id))\nconst exportError = computed(() => frame.exportError(props.id))\nconst exporting = computed(() => frame.exporting(props.id))\nconst EXPORT = 'export:'\nconst exportOpen = ref(false)\n\nfunction onSelect(value: DropdownValue | undefined) {\n if (typeof value !== 'string') return\n if (value.startsWith(EXPORT)) frame.exportTo(props.id, value.slice(EXPORT.length))\n else emitAction(value as WidgetAction)\n}\n</script>\n\n<template>\n <!-- outside the frame, which cuts off what overflows it -->\n <div v-if=\"widget && peers.length\" class=\"dou-dashboard__peers\" aria-hidden=\"true\">\n <span\n v-for=\"peer in peers\"\n :key=\"`${peer.client}:${peer.action}`\"\n :class=\"['dou-dashboard__peer', `is-${peer.action}`]\"\n :style=\"{ '--dou-dashboard-peer-color': peer.color }\"\n >\n {{ peerText(peer) }}\n </span>\n </div>\n <div\n v-if=\"widget\"\n ref=\"root\"\n :class=\"['dou-dashboard__widget', peers.length && 'has-peers']\"\n :style=\"peers.length ? { '--dou-dashboard-peer-color': peers[0]!.color } : undefined\"\n >\n <template v-if=\"!active\">\n <div class=\"dou-dashboard__header\">\n <div class=\"dou-dashboard__title\">{{ title }}</div>\n </div>\n <div class=\"dou-dashboard__body\" />\n </template>\n <component\n v-else\n :is=\"editing ? GridLayoutHandle : 'div'\"\n :as=\"editing ? 'header' : undefined\"\n class=\"dou-dashboard__header\"\n >\n <DouEditable\n v-if=\"editing\"\n v-model:editing=\"renaming\"\n class=\"dou-dashboard__title\"\n :model-value=\"title\"\n trigger=\"dblclick\"\n select-on-edit\n :aria-label=\"messages.titleField\"\n :data-dou-nodrag=\"renaming ? '' : undefined\"\n @submit=\"(value) => frame.rename(id, value)\"\n />\n <div v-else class=\"dou-dashboard__title\">{{ title }}</div>\n <div v-if=\"linked.length\" class=\"dou-dashboard__links\" data-dou-nodrag>\n <DouTag\n size=\"sm\"\n closable\n :close-label=\"format(messages.clearFilter, { value: linkLabel })\"\n @close=\"clearLinks\"\n >\n {{ format(messages.filteredBy, { value: linkLabel }) }}\n </DouTag>\n </div>\n <div class=\"dou-dashboard__actions\" data-dou-nodrag>\n <DouDropdown v-if=\"editing\" placement=\"bottom-end\" @select=\"onSelect\">\n <DouButton size=\"sm\" variant=\"ghost\" :aria-label=\"messages.widgetMenu\">\n <MoreHorizontalIcon />\n </DouButton>\n <template #menu>\n <DouDropdownItem value=\"settings\">{{ messages.settings }}</DouDropdownItem>\n <DouDropdownItem v-if=\"canFullscreen\" value=\"fullscreen\">\n {{ messages.fullscreen }}\n </DouDropdownItem>\n <DouDropdownSub v-if=\"exporters.length\" :title=\"messages.export\">\n <DouDropdownItem\n v-for=\"exporter in exporters\"\n :key=\"exporter.name\"\n :value=\"EXPORT + exporter.name\"\n :disabled=\"exporting\"\n >\n <template v-if=\"exporter.icon\" #prefix><component :is=\"exporter.icon\" /></template>\n {{ exporter.label }}\n </DouDropdownItem>\n </DouDropdownSub>\n <DouDropdownItem value=\"duplicate\" shortcut=\"mod+d\">\n {{ messages.duplicate }}\n </DouDropdownItem>\n <DouDropdownItem value=\"remove\" tone=\"danger\" shortcut=\"delete\" divided>\n {{ messages.remove }}\n </DouDropdownItem>\n </template>\n </DouDropdown>\n <DouTooltip v-if=\"!editing && exporters.length\" :content=\"messages.export\">\n <DouDropdown v-model:open=\"exportOpen\" placement=\"bottom-end\" @select=\"onSelect\">\n <DouButton\n size=\"sm\"\n variant=\"ghost\"\n :aria-label=\"messages.export\"\n :loading=\"exporting\"\n :disabled=\"exporting\"\n >\n <DownloadIcon />\n </DouButton>\n <template #menu>\n <DouDropdownItem\n v-for=\"exporter in exporters\"\n :key=\"exporter.name\"\n :value=\"EXPORT + exporter.name\"\n >\n <template v-if=\"exporter.icon\" #prefix><component :is=\"exporter.icon\" /></template>\n {{ exporter.label }}\n </DouDropdownItem>\n </template>\n </DouDropdown>\n </DouTooltip>\n <DouTooltip v-if=\"!editing && canFullscreen\" :content=\"messages.fullscreen\">\n <DouButton\n size=\"sm\"\n variant=\"ghost\"\n :aria-label=\"messages.fullscreen\"\n @click=\"emitAction('fullscreen')\"\n >\n <MaximizeIcon />\n </DouButton>\n </DouTooltip>\n </div>\n </component>\n <div v-if=\"exportError\" class=\"dou-dashboard__export-error\" data-dou-nodrag>\n <DouAlert tone=\"danger\" closable @close=\"frame.clearExportError(id)\">\n {{ exportError }}\n </DouAlert>\n </div>\n <WidgetBody\n v-if=\"active\"\n :widget=\"widget\"\n :type=\"type\"\n :editing=\"editing\"\n :messages=\"messages\"\n :set-props=\"frame.setProps\"\n :set-workbook=\"frame.setWorkbook\"\n />\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"widget-frame.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_Fragment","_renderList","_normalizeClass","_normalizeStyle","_toDisplayString","_createCommentVNode","_createElementVNode","_createBlock","_resolveDynamicComponent","GridLayoutHandle","_withCtx","_unref","_createVNode","_createTextVNode","CommentButton","_createSlots","WidgetBody"],"sources":["../../src/dashboard/widget-frame.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DownloadIcon, MaximizeIcon, MoreHorizontalIcon } from '@dou-ui/icons'\nimport {\n DouAlert,\n DouButton,\n DouDropdown,\n DouDropdownItem,\n DouDropdownSub,\n DouEditable,\n DouTag,\n DouTooltip,\n} from 'dou-ui'\nimport type { DropdownValue } from 'dou-ui'\nimport { computed, inject, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport GridLayoutHandle from '../grid/grid-handle.vue'\nimport { format } from '../locale'\nimport { frameContextKey } from './frame-context'\nimport type { WidgetAction } from './frame-context'\nimport { observersKey } from './observers'\nimport CommentButton from './comment-button.vue'\nimport WidgetBody from './widget-body.vue'\n\ndefineOptions({ name: 'DouDashboardWidget' })\n\nconst props = defineProps<{ id: string }>()\n\nconst frame = inject(frameContextKey)!\nconst widget = computed(() => frame.widget(props.id))\nconst type = computed(() => widget.value && frame.type(widget.value))\nconst title = computed(() => (widget.value ? frame.title(widget.value) : ''))\nconst editing = computed(() => frame.editing())\nconst messages = computed(() => frame.messages())\n/** The filters this widget set, each with a button to clear it. */\nconst linked = computed(() => frame.linked(props.id))\n/** All of them in one tag (a pivot table's click sets one per field), cleared together. */\nconst linkLabel = computed(() => linked.value.map((link) => link.label).join(' / '))\nfunction clearLinks() {\n for (const link of linked.value) frame.clearFilter(link.key)\n}\n\n/** Others at this widget, when editing together: an outline in the first one's color and their names. */\nconst peers = computed(() => frame.peers(props.id))\nconst peerText = (peer: { name: string; action: string }) => {\n const m = messages.value\n const text =\n peer.action === 'move'\n ? m.peerMoving\n : peer.action === 'resize'\n ? m.peerResizing\n : peer.action === 'settings'\n ? m.peerSettings\n : '{name}'\n return format(text, { name: peer.name })\n}\n\nconst renaming = ref(false)\n\n// Widgets far out of view show only their title until they come near: with\n// hundreds of widgets, their contents and controls are most of the mounting.\nconst root = ref<HTMLElement>()\nconst active = ref(frame.eager(props.id))\nconst observers = inject(observersKey)\nlet stop: (() => void) | undefined\nonMounted(() => {\n if (active.value || !observers) {\n active.value = true\n return\n }\n stop = observers.near(root.value!, () => {\n active.value = true\n stop?.()\n })\n})\nonBeforeUnmount(() => stop?.())\n// the dashboard draws everything for an export only when this widget isn't drawn yet\nwatch(active, (drawn) => frame.setDrawn(props.id, drawn), { immediate: true })\nonBeforeUnmount(() => frame.setDrawn(props.id, false))\n// drawn in full to export or print the dashboard, and kept that way\nwatch(\n () => frame.all(),\n (all) => {\n if (!all || active.value) return\n active.value = true\n stop?.()\n },\n { immediate: true },\n)\nconst canFullscreen = computed(() => type.value?.fullscreen !== false)\n\nconst emitAction = (action: WidgetAction) => frame.action(props.id, action)\n\n/** The file types this widget's content can be exported as; none unless it gives a workbook. */\nconst exporters = computed(() => frame.exporters(props.id))\nconst exportError = computed(() => frame.exportError(props.id))\nconst exporting = computed(() => frame.exporting(props.id))\nconst EXPORT = 'export:'\nconst exportOpen = ref(false)\n\nfunction onSelect(value: DropdownValue | undefined) {\n if (typeof value !== 'string') return\n if (value.startsWith(EXPORT)) frame.exportTo(props.id, value.slice(EXPORT.length))\n else emitAction(value as WidgetAction)\n}\n</script>\n\n<template>\n <!-- outside the frame, which cuts off what overflows it -->\n <div v-if=\"widget && peers.length\" class=\"dou-dashboard__peers\" aria-hidden=\"true\">\n <span\n v-for=\"peer in peers\"\n :key=\"`${peer.client}:${peer.action}`\"\n :class=\"['dou-dashboard__peer', `is-${peer.action}`]\"\n :style=\"{ '--dou-dashboard-peer-color': peer.color }\"\n >\n {{ peerText(peer) }}\n </span>\n </div>\n <div\n v-if=\"widget\"\n ref=\"root\"\n :class=\"['dou-dashboard__widget', peers.length && 'has-peers']\"\n :style=\"peers.length ? { '--dou-dashboard-peer-color': peers[0]!.color } : undefined\"\n >\n <template v-if=\"!active\">\n <div class=\"dou-dashboard__header\">\n <div class=\"dou-dashboard__title\">{{ title }}</div>\n </div>\n <div class=\"dou-dashboard__body\" />\n </template>\n <component\n v-else\n :is=\"editing ? GridLayoutHandle : 'div'\"\n :as=\"editing ? 'header' : undefined\"\n class=\"dou-dashboard__header\"\n >\n <DouEditable\n v-if=\"editing\"\n v-model:editing=\"renaming\"\n class=\"dou-dashboard__title\"\n :model-value=\"title\"\n trigger=\"dblclick\"\n select-on-edit\n :aria-label=\"messages.titleField\"\n :data-dou-nodrag=\"renaming ? '' : undefined\"\n @submit=\"(value) => frame.rename(id, value)\"\n />\n <div v-else class=\"dou-dashboard__title\">{{ title }}</div>\n <div v-if=\"linked.length\" class=\"dou-dashboard__links\" data-dou-nodrag>\n <DouTag\n size=\"sm\"\n closable\n :close-label=\"format(messages.clearFilter, { value: linkLabel })\"\n @close=\"clearLinks\"\n >\n {{ format(messages.filteredBy, { value: linkLabel }) }}\n </DouTag>\n </div>\n <div class=\"dou-dashboard__actions\" data-dou-nodrag>\n <CommentButton :id=\"id\" :comments=\"frame.comments\" :messages=\"messages\" />\n <DouDropdown v-if=\"editing\" placement=\"bottom-end\" @select=\"onSelect\">\n <DouButton size=\"sm\" variant=\"ghost\" :aria-label=\"messages.widgetMenu\">\n <MoreHorizontalIcon />\n </DouButton>\n <template #menu>\n <DouDropdownItem value=\"settings\">{{ messages.settings }}</DouDropdownItem>\n <DouDropdownItem v-if=\"canFullscreen\" value=\"fullscreen\">\n {{ messages.fullscreen }}\n </DouDropdownItem>\n <DouDropdownSub v-if=\"exporters.length\" :title=\"messages.export\">\n <DouDropdownItem\n v-for=\"exporter in exporters\"\n :key=\"exporter.name\"\n :value=\"EXPORT + exporter.name\"\n :disabled=\"exporting\"\n >\n <template v-if=\"exporter.icon\" #prefix><component :is=\"exporter.icon\" /></template>\n {{ exporter.label }}\n </DouDropdownItem>\n </DouDropdownSub>\n <DouDropdownItem value=\"duplicate\" shortcut=\"mod+d\">\n {{ messages.duplicate }}\n </DouDropdownItem>\n <DouDropdownItem value=\"remove\" tone=\"danger\" shortcut=\"delete\" divided>\n {{ messages.remove }}\n </DouDropdownItem>\n </template>\n </DouDropdown>\n <DouTooltip v-if=\"!editing && exporters.length\" :content=\"messages.export\">\n <DouDropdown v-model:open=\"exportOpen\" placement=\"bottom-end\" @select=\"onSelect\">\n <DouButton\n size=\"sm\"\n variant=\"ghost\"\n :aria-label=\"messages.export\"\n :loading=\"exporting\"\n :disabled=\"exporting\"\n >\n <DownloadIcon />\n </DouButton>\n <template #menu>\n <DouDropdownItem\n v-for=\"exporter in exporters\"\n :key=\"exporter.name\"\n :value=\"EXPORT + exporter.name\"\n >\n <template v-if=\"exporter.icon\" #prefix><component :is=\"exporter.icon\" /></template>\n {{ exporter.label }}\n </DouDropdownItem>\n </template>\n </DouDropdown>\n </DouTooltip>\n <DouTooltip v-if=\"!editing && canFullscreen\" :content=\"messages.fullscreen\">\n <DouButton\n size=\"sm\"\n variant=\"ghost\"\n :aria-label=\"messages.fullscreen\"\n @click=\"emitAction('fullscreen')\"\n >\n <MaximizeIcon />\n </DouButton>\n </DouTooltip>\n </div>\n </component>\n <div v-if=\"exportError\" class=\"dou-dashboard__export-error\" data-dou-nodrag>\n <DouAlert tone=\"danger\" closable @close=\"frame.clearExportError(id)\">\n {{ exportError }}\n </DouAlert>\n </div>\n <WidgetBody\n v-if=\"active\"\n :widget=\"widget\"\n :type=\"type\"\n :editing=\"editing\"\n :messages=\"messages\"\n :set-props=\"frame.setProps\"\n :set-workbook=\"frame.setWorkbook\"\n />\n </div>\n</template>\n"],"mappings":"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"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["GridLayout","GridLayoutHandle","Dashboard","DashboardPalette","DashboardFilterBar"],"sources":["../src/index.ts"],"sourcesContent":["import { withInstall } from 'dou-ui'\nimport GridLayout from './grid/grid-layout.vue'\nimport GridLayoutHandle from './grid/grid-handle.vue'\nimport Dashboard from './dashboard/dashboard.vue'\nimport DashboardPalette from './dashboard/palette.vue'\nimport DashboardFilterBar from './dashboard/filter-bar.vue'\n\nexport const DouGridLayout = withInstall(GridLayout)\nexport const DouGridLayoutHandle = withInstall(GridLayoutHandle)\nexport const DouDashboard = withInstall(Dashboard)\nexport const DouDashboardPalette = withInstall(DashboardPalette)\nexport const DouDashboardFilterBar = withInstall(DashboardFilterBar)\n\nexport type {\n DashboardAddOptions,\n DashboardEmits,\n DashboardExportErrorEvent,\n DashboardExportOptions,\n DashboardSaveOptions,\n DashboardExpose,\n DashboardFilterBarProps,\n DashboardPaletteProps,\n DashboardProps,\n} from './dashboard/types'\nexport type { DashboardDocument, DashboardPlace, DashboardWidget } from './core/types'\nexport { checkDocument, emptyDocument, isDashboardPlace, migrateDocument } from './core/document'\nexport type { CheckDocumentOptions, DocumentProblem } from './core/document'\nexport { applySteps, DashboardTransaction, replaceWidgets, sameValue } from './core/transaction'\nexport type {\n DashboardCollaboration,\n DashboardCollaborationHost,\n DashboardPeer,\n DashboardPresence,\n DashboardPresenceAction,\n} from './core/collaboration'\nexport type {\n DashboardStep,\n DashboardTransactionMeta,\n DashboardWidgetPatch,\n} from './core/transaction'\nexport { DashboardHistory } from './core/history'\nexport { defineDashboardWidget } from './widget/define'\nexport type { DashboardWidgetSize, DashboardWidgetType } from './widget/define'\nexport { useDashboardWidget } from './widget/context'\nexport { isEmptyFilter } from './data/filters'\nexport type { DashboardImageOptions } from './dashboard/export'\nexport type {\n DashboardDateRangeFilterField,\n DashboardFilterField,\n DashboardFilters,\n DashboardLinkedFilter,\n DashboardSearchFilterField,\n DashboardSelectFilterField,\n DashboardSetFilterOptions,\n DashboardSourceContext,\n DashboardSourceLoad,\n DashboardSourceOptions,\n DashboardSources,\n} from './data/types'\nexport type {\n DashboardWidgetContext,\n DashboardWidgetState,\n DashboardWidgetStatus,\n} from './widget/context'\n\nexport type {\n GridChangeEvent,\n GridChangeReason,\n GridDragEndEvent,\n GridDragEvent,\n GridDropEvent,\n GridDropItem,\n GridItemSlotProps,\n GridLayoutEmits,\n GridLayoutExpose,\n GridLayoutProps,\n GridLayouts,\n GridPlace,\n GridResizeHandle,\n} from './grid/types'\nexport {\n compactLayout,\n deriveLayout,\n findPlace,\n fitItem,\n layoutHeight,\n moveItem,\n moveItemBy,\n normalizeLayout,\n overlaps,\n resizeItem,\n resizeItemBy,\n} from './layout'\nexport type { GridCompact, GridItem, GridLayoutOptions, GridPosition, GridSize } from './layout'\nexport { dashboardLocales, useDashboardMessages } from './locale'\nexport type { DashboardMessages, DashboardMessagesOverride } from './locale'\n\ndeclare module 'vue' {\n export interface GlobalComponents {\n DouGridLayout: typeof DouGridLayout\n DouGridLayoutHandle: typeof DouGridLayoutHandle\n DouDashboard: typeof DouDashboard\n DouDashboardPalette: typeof DouDashboardPalette\n DouDashboardFilterBar: typeof DouDashboardFilterBar\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAOA,IAAa,gBAAgB,YAAYA,mBAAU;AACnD,IAAa,sBAAsB,YAAYC,mBAAgB;AAC/D,IAAa,eAAe,YAAYC,iBAAS;AACjD,IAAa,sBAAsB,YAAYC,eAAgB;AAC/D,IAAa,wBAAwB,YAAYC,kBAAkB"}
1
+ {"version":3,"file":"index.js","names":["GridLayout","GridLayoutHandle","Dashboard","DashboardPalette","DashboardFilterBar"],"sources":["../src/index.ts"],"sourcesContent":["import { withInstall } from 'dou-ui'\nimport GridLayout from './grid/grid-layout.vue'\nimport GridLayoutHandle from './grid/grid-handle.vue'\nimport Dashboard from './dashboard/dashboard.vue'\nimport DashboardPalette from './dashboard/palette.vue'\nimport DashboardFilterBar from './dashboard/filter-bar.vue'\n\nexport const DouGridLayout = withInstall(GridLayout)\nexport const DouGridLayoutHandle = withInstall(GridLayoutHandle)\nexport const DouDashboard = withInstall(Dashboard)\nexport const DouDashboardPalette = withInstall(DashboardPalette)\nexport const DouDashboardFilterBar = withInstall(DashboardFilterBar)\n\nexport type {\n DashboardAddOptions,\n DashboardEmits,\n DashboardExportErrorEvent,\n DashboardExportOptions,\n DashboardSaveOptions,\n DashboardCommentAnchor,\n DashboardExpose,\n DashboardFilterBarProps,\n DashboardPaletteProps,\n DashboardProps,\n} from './dashboard/types'\nexport type { DashboardDocument, DashboardPlace, DashboardWidget } from './core/types'\nexport { checkDocument, emptyDocument, isDashboardPlace, migrateDocument } from './core/document'\nexport type { CheckDocumentOptions, DocumentProblem } from './core/document'\nexport { applySteps, DashboardTransaction, replaceWidgets, sameValue } from './core/transaction'\nexport type { ReplaceWidgetsOptions } from './core/transaction'\nexport type {\n DashboardCollaboration,\n DashboardCollaborationHost,\n DashboardPeer,\n DashboardPresence,\n DashboardPresenceAction,\n} from './core/collaboration'\nexport type {\n DashboardStep,\n DashboardTransactionMeta,\n DashboardWidgetPatch,\n} from './core/transaction'\nexport { DashboardHistory } from './core/history'\nexport { defineDashboardWidget } from './widget/define'\nexport type { DashboardWidgetSize, DashboardWidgetType } from './widget/define'\nexport { useDashboardWidget } from './widget/context'\nexport { isEmptyFilter } from './data/filters'\nexport type { DashboardImageOptions } from './dashboard/export'\nexport type {\n DashboardDateRangeFilterField,\n DashboardFilterField,\n DashboardFilters,\n DashboardLinkedFilter,\n DashboardSearchFilterField,\n DashboardSelectFilterField,\n DashboardSetFilterOptions,\n DashboardSourceContext,\n DashboardSourceLoad,\n DashboardSourceOptions,\n DashboardSources,\n} from './data/types'\nexport type {\n DashboardWidgetContext,\n DashboardWidgetState,\n DashboardWidgetStatus,\n} from './widget/context'\n\nexport type {\n GridChangeEvent,\n GridChangeReason,\n GridDragEndEvent,\n GridDragEvent,\n GridDropEvent,\n GridDropItem,\n GridItemSlotProps,\n GridLayoutEmits,\n GridLayoutExpose,\n GridLayoutProps,\n GridLayouts,\n GridPlace,\n GridResizeHandle,\n} from './grid/types'\nexport {\n compactLayout,\n deriveLayout,\n findPlace,\n fitItem,\n layoutHeight,\n moveItem,\n moveItemBy,\n normalizeLayout,\n overlaps,\n resizeItem,\n resizeItemBy,\n} from './layout'\nexport type { GridCompact, GridItem, GridLayoutOptions, GridPosition, GridSize } from './layout'\nexport { dashboardLocales, useDashboardMessages } from './locale'\nexport type { DashboardMessages, DashboardMessagesOverride } from './locale'\n\ndeclare module 'vue' {\n export interface GlobalComponents {\n DouGridLayout: typeof DouGridLayout\n DouGridLayoutHandle: typeof DouGridLayoutHandle\n DouDashboard: typeof DouDashboard\n DouDashboardPalette: typeof DouDashboardPalette\n DouDashboardFilterBar: typeof DouDashboardFilterBar\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAOA,IAAa,gBAAgB,YAAYA,mBAAU;AACnD,IAAa,sBAAsB,YAAYC,mBAAgB;AAC/D,IAAa,eAAe,YAAYC,iBAAS;AACjD,IAAa,sBAAsB,YAAYC,eAAgB;AAC/D,IAAa,wBAAwB,YAAYC,kBAAkB"}
package/dist/locale.js CHANGED
@@ -22,6 +22,8 @@ var zhCN = {
22
22
  nothingToExport: "没有可导出的数据",
23
23
  duplicate: "复制一份",
24
24
  remove: "删除",
25
+ comment: "评论",
26
+ comments: "{count} 条评论",
25
27
  settingsTitle: "{title}的设置",
26
28
  titleField: "标题",
27
29
  added: "已添加 {item}",
@@ -94,6 +96,8 @@ var zhTW = {
94
96
  nothingToExport: "沒有可匯出的資料",
95
97
  duplicate: "複製一份",
96
98
  remove: "刪除",
99
+ comment: "評論",
100
+ comments: "{count} 則評論",
97
101
  settingsTitle: "{title}的設定",
98
102
  titleField: "標題",
99
103
  added: "已新增 {item}",
@@ -166,6 +170,8 @@ var en = {
166
170
  nothingToExport: "There is no data to export",
167
171
  duplicate: "Duplicate",
168
172
  remove: "Remove",
173
+ comment: "Comment",
174
+ comments: "{count} comments",
169
175
  settingsTitle: "{title} settings",
170
176
  titleField: "Title",
171
177
  added: "Added {item}",