@d3-polytree/editor 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -287,7 +287,7 @@ function fromHtml(html) {
287
287
  }
288
288
  var FORM_CONTROLS = /* @__PURE__ */ new Set(["INPUT", "TEXTAREA", "SELECT"]);
289
289
  var _PropertiesPanel = class _PropertiesPanel {
290
- constructor(sideTabsProvider, eventBus, propertiesProvider, diagramSettings) {
290
+ constructor(sideTabsProvider, eventBus, propertiesProvider, diagramSettings, commandStack) {
291
291
  this._entries = {};
292
292
  this._container = null;
293
293
  this._tabsEl = null;
@@ -295,9 +295,27 @@ var _PropertiesPanel = class _PropertiesPanel {
295
295
  this._eventBus = eventBus;
296
296
  this._propertiesProvider = propertiesProvider;
297
297
  this._diagramSettings = diagramSettings;
298
+ this._commandStack = commandStack;
299
+ this._registerUpdatePropertiesCommand();
298
300
  this._registerSideTab(sideTabsProvider);
299
301
  this._registerSelectionListener();
300
302
  }
303
+ /**
304
+ * Register the `element.updateProperties` command. Its apply logic is
305
+ * editor-specific (a property `scope` plus the provider's drawing update), so
306
+ * the panel — which owns both — registers it on the shared stack rather than
307
+ * the core modelling orchestrator.
308
+ */
309
+ _registerUpdatePropertiesCommand() {
310
+ const apply = (ctx, props) => {
311
+ ctx.scope.set(ctx.definition, props);
312
+ this._propertiesProvider.updateDrawing(ctx.definition);
313
+ };
314
+ this._commandStack.registerHandler("element.updateProperties", {
315
+ execute: (ctx) => apply(ctx, ctx.after),
316
+ revert: (ctx) => apply(ctx, ctx.before)
317
+ });
318
+ }
301
319
  _registerSideTab(provider) {
302
320
  provider.registerSideTab(
303
321
  {
@@ -379,10 +397,16 @@ var _PropertiesPanel = class _PropertiesPanel {
379
397
  if (!entry) {
380
398
  return;
381
399
  }
382
- const props = {};
383
- deepSet(props, entryId, newValue);
384
- entry.scope.set(entry.definition, props);
385
- this._propertiesProvider.updateDrawing(entry.definition);
400
+ const after = {};
401
+ deepSet(after, entryId, newValue);
402
+ const before = {};
403
+ deepSet(before, entryId, deepGet(entry.definition, entryId));
404
+ this._commandStack.execute("element.updateProperties", {
405
+ scope: entry.scope,
406
+ definition: entry.definition,
407
+ before,
408
+ after
409
+ });
386
410
  }
387
411
  _selectTab(tabId) {
388
412
  this._tabsEl?.querySelectorAll(".tab-sheet").forEach((tab) => {
@@ -448,7 +472,8 @@ _PropertiesPanel.$inject = [
448
472
  "sideTabsProvider",
449
473
  "eventBus",
450
474
  "propertiesProvider",
451
- "d3polytree.definitions.settings"
475
+ "d3polytree.definitions.settings",
476
+ "commandStack"
452
477
  ];
453
478
  _PropertiesPanel.HTML_MARKUP = '<div id="pfdjs-pp-container"><div class="pfdjs-pp-tabs"><ul class="tab-sheets"></ul></div><div class="pfdjs-pp-contents"></div></div>';
454
479
  var PropertiesPanel = _PropertiesPanel;
@@ -462,10 +487,41 @@ var propertiesPanelModule = {
462
487
  // src/index.ts
463
488
  var INITIAL_DIAGRAM = '<?xml version="1.0" encoding="UTF-8"?><pfdn:diagram xmlns:pfdn="http://pfdn" xmlns="http://pfdn"><settings author="No Author" name="No Name Diagram" status="1"><zoom><offset x="0" y="0" /><scale>1</scale></zoom><grid /></settings><node id="node_1" label="label_1" status="1"><position x="20" y="100" /></node><label id="label_1" fontSize="12" isReadOnly="true" status="1"><position x="33" y="140" /><text>Node 1</text></label></pfdn:diagram>';
464
489
  var _Editor = class _Editor extends InteractiveViewer {
465
- constructor() {
466
- super(...arguments);
490
+ constructor(options = {}) {
491
+ super(options);
467
492
  /** The document a fresh editor opens with (used by {@link createDiagram}). */
468
493
  this.initialDiagram = INITIAL_DIAGRAM;
494
+ this._onKeydown = (event) => this._handleKeydown(event);
495
+ options.container?.addEventListener("keydown", this._onKeydown);
496
+ }
497
+ _handleKeydown(event) {
498
+ const target = event.target;
499
+ if (target && (target.tagName === "INPUT" || target.tagName === "TEXTAREA")) {
500
+ return;
501
+ }
502
+ if (!this.getHost()) {
503
+ return;
504
+ }
505
+ const mod = event.ctrlKey || event.metaKey;
506
+ if (!mod) {
507
+ return;
508
+ }
509
+ const key = event.key.toLowerCase();
510
+ if (key === "z" && event.shiftKey) {
511
+ event.preventDefault();
512
+ this.redo();
513
+ } else if (key === "z") {
514
+ event.preventDefault();
515
+ this.undo();
516
+ } else if (key === "y") {
517
+ event.preventDefault();
518
+ this.redo();
519
+ }
520
+ }
521
+ /** Tear down the editor, removing the keyboard binding. */
522
+ destroy() {
523
+ this.options.container?.removeEventListener("keydown", this._onKeydown);
524
+ super.destroy();
469
525
  }
470
526
  /** (Re)open the initial diagram. */
471
527
  createDiagram() {
@@ -478,9 +534,16 @@ var _Editor = class _Editor extends InteractiveViewer {
478
534
  ...Viewer.modules
479
535
  ];
480
536
  }
481
- /** Create a node (and its associated label) at an optional position. */
537
+ /**
538
+ * Create a node (and its associated label) at an optional position.
539
+ *
540
+ * Routed through the command stack so it persists and is undoable (since B10
541
+ * the draw-layer `.created` event no longer persists on its own).
542
+ */
482
543
  createNode(parameters = {}) {
483
- return this.get("modellingNodes").create(parameters);
544
+ const ctx = { className: "node", parameters: [parameters] };
545
+ this.get("commandStack").execute("element.create", ctx);
546
+ return ctx.created;
484
547
  }
485
548
  /** Select an element by definition (e.g. to prepare a delete). */
486
549
  select(definition) {
@@ -493,6 +556,22 @@ var _Editor = class _Editor extends InteractiveViewer {
493
556
  deleteSelected() {
494
557
  this.get("selection").deleteSelected();
495
558
  }
559
+ /** Undo the last edit (a whole gesture is one step). No-op if nothing to undo. */
560
+ undo() {
561
+ this.get("commandStack").undo();
562
+ }
563
+ /** Redo the last undone edit. No-op if nothing to redo. */
564
+ redo() {
565
+ this.get("commandStack").redo();
566
+ }
567
+ /** Whether there is an edit to undo. */
568
+ canUndo() {
569
+ return this.get("commandStack").canUndo();
570
+ }
571
+ /** Whether there is an undone edit to redo. */
572
+ canRedo() {
573
+ return this.get("commandStack").canRedo();
574
+ }
496
575
  };
497
576
  /** Editing modules on top of the interaction layer. */
498
577
  _Editor.editionModules = [
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/properties-panel/utils.ts","../src/properties-panel/EntryFactory.ts","../src/properties-panel/PfdnPropertiesProvider.ts","../src/properties-panel/PropertiesPanel.ts","../src/properties-panel/index.ts"],"sourcesContent":["/**\n * @d3-polytree/editor — create and modify polytree diagrams.\n *\n * Extends the {@link InteractiveViewer} with the editing layer: element\n * dragging plus the modelling create/save/delete flows. Element creation is\n * exposed programmatically here; the palette toolbar UI is layered on next.\n */\nimport { InteractiveViewer, type InteractiveViewerOptions } from '@d3-polytree/interactive-viewer';\nimport { Viewer } from '@d3-polytree/viewer';\nimport {\n dragModule,\n modellingModule,\n exportingModule,\n localStorageModule,\n uploadModule,\n paletteModule,\n resizeElementModule,\n type DiagramModule,\n type DrawingRegistry,\n type ModellingNodes,\n type ModellingModelElement,\n type CreateParameters,\n type Selection\n} from '@d3-polytree/core';\n// The properties panel used to be its own package; it is now folded in here\n// (the editor was its only consumer) and re-exported below.\nimport {\n entryFactoryModule,\n pfdnPropertiesProviderModule,\n propertiesPanelModule\n} from './properties-panel';\n\nexport * from './properties-panel';\n\n/** The document a fresh editor opens with. */\nconst INITIAL_DIAGRAM =\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>' +\n '<pfdn:diagram xmlns:pfdn=\"http://pfdn\" xmlns=\"http://pfdn\">' +\n '<settings author=\"No Author\" name=\"No Name Diagram\" status=\"1\">' +\n '<zoom><offset x=\"0\" y=\"0\" /><scale>1</scale></zoom><grid />' +\n '</settings>' +\n '<node id=\"node_1\" label=\"label_1\" status=\"1\"><position x=\"20\" y=\"100\" /></node>' +\n '<label id=\"label_1\" fontSize=\"12\" isReadOnly=\"true\" status=\"1\">' +\n '<position x=\"33\" y=\"140\" /><text>Node 1</text></label>' +\n '</pfdn:diagram>';\n\nexport type EditorOptions = InteractiveViewerOptions;\n\nexport class Editor extends InteractiveViewer {\n /** Editing modules on top of the interaction layer. */\n static readonly editionModules: readonly DiagramModule[] = [\n dragModule as DiagramModule,\n modellingModule as DiagramModule,\n exportingModule as DiagramModule,\n localStorageModule as DiagramModule,\n uploadModule as DiagramModule,\n paletteModule as DiagramModule,\n resizeElementModule as DiagramModule,\n // the properties panel (registers a side tab; side-tabs + search-panel are\n // inherited from InteractiveViewer)\n entryFactoryModule as DiagramModule,\n pfdnPropertiesProviderModule as DiagramModule,\n propertiesPanelModule as DiagramModule\n ];\n\n /** The document a fresh editor opens with (used by {@link createDiagram}). */\n initialDiagram = INITIAL_DIAGRAM;\n\n /** (Re)open the initial diagram. */\n createDiagram(): Promise<void> {\n return this.importDiagram(this.initialDiagram);\n }\n\n getModules(): readonly DiagramModule[] {\n // interaction + editing features first (they subscribe / swap the layer),\n // then the drawers\n return [\n ...InteractiveViewer.interactionModules,\n ...Editor.editionModules,\n ...Viewer.modules\n ];\n }\n\n /** Create a node (and its associated label) at an optional position. */\n createNode(parameters: CreateParameters = {}): ModellingModelElement {\n return this.get<ModellingNodes>('modellingNodes').create(parameters);\n }\n\n /** Select an element by definition (e.g. to prepare a delete). */\n select(definition: ModellingModelElement): void {\n const element = this.get<DrawingRegistry>('drawingRegistry').get(definition.id as string);\n if (element) {\n this.get<Selection>('selection').select(element, definition);\n }\n }\n\n /** Delete the current selection (cascading to associated labels). */\n deleteSelected(): void {\n this.get<Selection>('selection').deleteSelected();\n }\n}\n\nexport default Editor;\n","/** A moddle model element as read/written by the properties panel. */\nexport interface Definition {\n id?: string;\n label?: Definition;\n $instanceOf(type: string): boolean;\n get(property: string): unknown;\n [key: string]: unknown;\n}\n\n/** `definition.$instanceOf(elementType)` — ported from `utils/modelUtils`. */\nexport function is(definition: Definition, elementType: string): boolean {\n return definition.$instanceOf(elementType);\n}\n\n/** Read a dotted property path (`label.text`) by plain property access. */\nexport function deepGet(obj: unknown, path: string): unknown {\n return path\n .split('.')\n .reduce<unknown>(\n (o, k) => (o == null ? undefined : (o as Record<string, unknown>)[k]),\n obj\n );\n}\n\n/** Write a dotted property path, creating intermediate objects as needed. */\nexport function deepSet(obj: Record<string, unknown>, path: string, value: unknown): void {\n const keys = path.split('.');\n let cursor = obj;\n for (let i = 0; i < keys.length - 1; i += 1) {\n const key = keys[i];\n if (cursor[key] == null || typeof cursor[key] !== 'object') {\n cursor[key] = {};\n }\n cursor = cursor[key] as Record<string, unknown>;\n }\n cursor[keys[keys.length - 1]] = value;\n}\n\n/** Trailing-nothing leading-edge? No — trailing debounce, like lodash's default. */\nexport function debounce<A extends unknown[]>(\n fn: (...args: A) => void,\n wait: number\n): (...args: A) => void {\n let timer: ReturnType<typeof setTimeout> | undefined;\n return (...args: A) => {\n if (timer) {\n clearTimeout(timer);\n }\n timer = setTimeout(() => fn(...args), wait);\n };\n}\n\n/** Title-case a token (`lineColor` → `Line Color`, `aws-ec2` → `Aws Ec 2`). */\nexport function startCase(input: string): string {\n return input\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/([a-zA-Z])([0-9])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim()\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\n/** Whether a string is a `#rrggbb` colour (accepted by `<input type=color>`). */\nexport function isHexColor(value: unknown): value is string {\n return typeof value === 'string' && /^#[0-9a-fA-F]{6}$/.test(value);\n}\n","import type EventEmitter from 'eventemitter3';\nimport { deepGet, deepSet, isHexColor, type Definition } from './utils';\n\n/** A `{name,value}` option for a select entry. */\nexport interface SelectOption {\n name: string;\n value: string;\n}\n\n/** Options accepted when building an entry. */\nexport interface EntryOptions {\n id: string;\n modelProperty: string;\n label?: string;\n description?: string;\n type?: string;\n allowEmpty?: boolean;\n selectOptions?: SelectOption[];\n}\n\n/** A rendered property entry: its markup plus get/set behaviour. */\nexport interface EntryResource extends EntryOptions {\n html: string;\n get: (element: Definition, formNode: HTMLElement) => void;\n set: (element: Definition, values: Record<string, unknown>) => boolean;\n validate: () => Record<string, unknown>;\n triggerUpdate: (propertyId: string, element: Definition) => void;\n}\n\nfunction ensureNotNull(prop: string | undefined): string {\n if (!prop) {\n throw new Error(`${prop} must be set.`);\n }\n return prop;\n}\n\n/**\n * Builds property-panel entries (text / select / colour / spreadsheet). Ported\n * from `@d3-polytree/properties-panel`'s `entryFactory/*`, de-jQuery-ed onto\n * native DOM; the colour entry uses a native `<input type=\"color\">` in place of\n * spectrum-colorpicker.\n */\nexport class EntryFactory {\n static readonly $inject = ['eventBus'];\n\n private readonly _eventBus: EventEmitter;\n\n constructor(eventBus: EventEmitter) {\n this._eventBus = eventBus;\n }\n\n setDefaultParameters(options: EntryOptions): EntryResource {\n const eventBus = this._eventBus;\n\n const defaultGet = (element: Definition, formNode: HTMLElement): void => {\n const prop = ensureNotNull(options.modelProperty);\n const value = deepGet(element, prop);\n const input = formNode.querySelector('input');\n if (input) {\n (input as HTMLInputElement).value = value == null ? '' : String(value);\n }\n };\n\n const defaultSet = (element: Definition, values: Record<string, unknown>): boolean => {\n const prop = ensureNotNull(options.modelProperty);\n deepSet(element as unknown as Record<string, unknown>, prop, deepGet(values, prop));\n return true;\n };\n\n const triggerUpdate = (propertyId: string, element: Definition): void => {\n eventBus.emit('PropertiesPanel.propertyChanged', propertyId, element);\n };\n\n return {\n html: '',\n description: '',\n get: defaultGet,\n set: defaultSet,\n validate: () => ({}),\n ...options,\n triggerUpdate\n };\n }\n\n textField(options: EntryOptions): EntryResource {\n return textInputField(this.setDefaultParameters(options));\n }\n\n selectBox(options: EntryOptions): EntryResource {\n return selectBoxField(this.setDefaultParameters(options));\n }\n\n colorPicker(options: EntryOptions): EntryResource {\n return colorPickerField(this.setDefaultParameters(options));\n }\n\n spreadsheet(options: EntryOptions): EntryResource {\n // Placeholder in the source engine; kept as an API-compatible no-op.\n return this.setDefaultParameters(options);\n }\n}\n\nfunction fieldWrapper(resource: EntryResource, inner: string): string {\n const label = resource.label ?? resource.id;\n return (\n `<div class=\"pfdjs-pp-field-wrapper\">` +\n `<label for=\"pfdjs-${resource.id}\">${label}</label>${inner}</div>`\n );\n}\n\nfunction textInputField(resource: EntryResource): EntryResource {\n const type = resource.type ?? 'text';\n resource.html = fieldWrapper(\n resource,\n `<input id=\"pfdjs-${resource.id}\" type=\"${type}\" name=\"${resource.modelProperty}\" />`\n );\n return resource;\n}\n\nfunction selectBoxField(resource: EntryResource): EntryResource {\n const allowEmpty = resource.allowEmpty ?? true;\n const options = Array.isArray(resource.selectOptions)\n ? resource.selectOptions.concat(allowEmpty ? [{ name: '', value: '' }] : [])\n : [{ name: '', value: '' }];\n\n const optionsHtml = options\n .map((o) => `<option value=\"${o.value}\">${o.name}</option>`)\n .join('');\n resource.html = fieldWrapper(\n resource,\n `<select id=\"pfdjs-${resource.id}\" name=\"${resource.modelProperty}\">${optionsHtml}</select>`\n );\n\n resource.get = (element, formNode) => {\n const value = element.get(resource.modelProperty) ?? 'default';\n formNode\n .querySelectorAll<HTMLOptionElement>(`select#pfdjs-${resource.id} > option`)\n .forEach((option) => {\n option.selected = option.value === value;\n });\n };\n\n return resource;\n}\n\nfunction colorPickerField(resource: EntryResource): EntryResource {\n resource.html = fieldWrapper(\n resource,\n `<input id=\"pfdjs-${resource.id}\" type=\"color\" name=\"${resource.modelProperty}\" />`\n );\n resource.get = (element, formNode) => {\n const input = formNode.querySelector<HTMLInputElement>('input[type=color]');\n const value = deepGet(element, resource.modelProperty);\n if (input && isHexColor(value)) {\n input.value = value;\n }\n };\n return resource;\n}\n\n/** didi module contributing the entry factory. */\nexport const entryFactoryModule = {\n __init__: ['entryFactory'],\n entryFactory: ['type', EntryFactory]\n};\n","import type EventEmitter from 'eventemitter3';\nimport type { EntryFactory, EntryResource } from './EntryFactory';\nimport { is, startCase, type Definition } from './utils';\n\n/** A group of entries within a tab. */\nexport interface PropertiesGroup {\n id: string;\n label: string;\n entries: EntryResource[];\n}\n\n/** A properties-panel tab. */\nexport interface PropertiesTab {\n id: string;\n label: string;\n groups: PropertiesGroup[];\n}\n\n/** Icon registry token: icon type → SVG source. */\nexport type IconMap = Record<string, string>;\n\n/** A properties provider: supplies the tabs for a selected element. */\nexport interface PropertiesProvider {\n getTabs(element: Definition): PropertiesTab[];\n updateDrawing(definition: Definition): void;\n}\n\n// --- pfdn property parts (ported from provider/pfdn/tabs/parts/*) ------------\n\nfunction nameProps(group: PropertiesGroup, element: Definition, factory: EntryFactory): void {\n if (is(element, 'pfdn:Node')) {\n group.entries.push(factory.textField({ id: 'name', label: 'Name', modelProperty: 'name' }));\n group.entries.push(factory.textField({ id: 'tag', label: 'Tag', modelProperty: 'tag' }));\n group.entries.push(\n factory.textField({ id: 'label.text', label: 'Diagram label', modelProperty: 'label.text' })\n );\n } else if (is(element, 'pfdn:Settings')) {\n group.entries.push(factory.textField({ id: 'name', label: 'Diagram name', modelProperty: 'name' }));\n group.entries.push(factory.textField({ id: 'author', label: \"Author's name\", modelProperty: 'author' }));\n } else if (is(element, 'pfdn:Link')) {\n group.entries.push(\n factory.textField({ id: 'label.text', label: 'Diagram label', modelProperty: 'label.text' })\n );\n } else if (is(element, 'pfdn:Label')) {\n group.entries.push(factory.textField({ id: 'text', label: 'Label', modelProperty: 'text' }));\n }\n}\n\nfunction nodeFormatProps(\n group: PropertiesGroup,\n element: Definition,\n factory: EntryFactory,\n icons: IconMap\n): void {\n if (!is(element, 'pfdn:Node')) {\n return;\n }\n const selectOptions = Object.keys(icons).map((key) => ({ value: key, name: startCase(key) }));\n group.entries.push(\n factory.selectBox({\n id: 'type',\n label: 'Icon',\n modelProperty: 'type',\n allowEmpty: false,\n selectOptions\n })\n );\n group.entries.push(\n factory.textField({ id: 'size', label: 'Size', modelProperty: 'size', type: 'number' })\n );\n}\n\nfunction linkFormatProps(group: PropertiesGroup, element: Definition, factory: EntryFactory): void {\n if (!is(element, 'pfdn:Link')) {\n return;\n }\n group.entries.push(\n factory.textField({ id: 'lineWidth', label: 'Line width', modelProperty: 'lineWidth', type: 'number' })\n );\n group.entries.push(\n factory.colorPicker({ id: 'lineColor', label: 'Line color', modelProperty: 'lineColor' })\n );\n}\n\nfunction labelFormatProps(group: PropertiesGroup, element: Definition, factory: EntryFactory): void {\n if (is(element, 'pfdn:Node') || is(element, 'pfdn:Link')) {\n group.entries.push(\n factory.textField({\n id: 'label.fontSize',\n label: 'Font size',\n modelProperty: 'label.fontSize',\n type: 'number'\n })\n );\n group.entries.push(\n factory.colorPicker({ id: 'label.color', label: 'Color', modelProperty: 'label.color' })\n );\n } else if (is(element, 'pfdn:Label')) {\n group.entries.push(\n factory.textField({ id: 'fontSize', label: 'Font size', modelProperty: 'fontSize', type: 'number' })\n );\n group.entries.push(factory.colorPicker({ id: 'color', label: 'Color', modelProperty: 'color' }));\n }\n}\n\nfunction gridFormatProps(group: PropertiesGroup, element: Definition, factory: EntryFactory): void {\n if (!is(element, 'pfdn:Settings')) {\n return;\n }\n group.entries.push(\n factory.colorPicker({ id: 'backgroundColor', label: 'Background color', modelProperty: 'backgroundColor' })\n );\n group.entries.push(\n factory.colorPicker({ id: 'grid.lineColor', label: 'Line color', modelProperty: 'grid.lineColor' })\n );\n group.entries.push(\n factory.textField({ id: 'grid.size', label: 'Square size', modelProperty: 'grid.size', type: 'number' })\n );\n group.entries.push(\n factory.textField({ id: 'grid.lineWidth', label: 'Line width', modelProperty: 'grid.lineWidth', type: 'number' })\n );\n}\n\n/**\n * The PFDN properties provider: builds the Properties + Format tabs for the\n * selected element, and applies edits back to the drawing. Ported from\n * `provider/pfdn/*`.\n */\nexport class PfdnPropertiesProvider implements PropertiesProvider {\n static readonly $inject = ['icons', 'entryFactory', 'eventBus'];\n\n private readonly _icons: IconMap;\n private readonly _entryFactory: EntryFactory;\n private readonly _eventBus: EventEmitter;\n\n constructor(icons: IconMap, entryFactory: EntryFactory, eventBus: EventEmitter) {\n this._icons = icons;\n this._entryFactory = entryFactory;\n this._eventBus = eventBus;\n }\n\n updateDrawing(definition: Definition): void {\n if (is(definition, 'pfdn:Settings')) {\n this._eventBus.emit('canvas.resized');\n return;\n }\n this._eventBus.emit('element.updated', definition.id, definition);\n if (is(definition, 'pfdn:Link') || is(definition, 'pfdn:Node')) {\n const label = definition.label;\n if (label) {\n this._eventBus.emit('element.updated', label.id, label);\n }\n }\n }\n\n getTabs(element: Definition): PropertiesTab[] {\n const factory = this._entryFactory;\n return [this._propertiesTab(element, factory), this._formatTab(element, factory)];\n }\n\n private _propertiesTab(element: Definition, factory: EntryFactory): PropertiesTab {\n const general: PropertiesGroup = { id: 'general', label: 'General', entries: [] };\n nameProps(general, element, factory);\n return { id: 'properties', label: 'Properties', groups: [general] };\n }\n\n private _formatTab(element: Definition, factory: EntryFactory): PropertiesTab {\n const elementFormat: PropertiesGroup = { id: 'elementFormat', label: 'Element format', entries: [] };\n const labelFormat: PropertiesGroup = { id: 'labelFormat', label: 'Label format', entries: [] };\n const gridFormat: PropertiesGroup = { id: 'gridFormat', label: 'Grid format', entries: [] };\n\n nodeFormatProps(elementFormat, element, factory, this._icons);\n linkFormatProps(elementFormat, element, factory);\n labelFormatProps(labelFormat, element, factory);\n gridFormatProps(gridFormat, element, factory);\n\n return { id: 'format', label: 'Format', groups: [elementFormat, labelFormat, gridFormat] };\n }\n}\n\n/** didi module contributing the PFDN properties provider. */\nexport const pfdnPropertiesProviderModule = {\n __init__: ['propertiesProvider'],\n propertiesProvider: ['type', PfdnPropertiesProvider]\n};\n","import type EventEmitter from 'eventemitter3';\nimport type { EntryResource } from './EntryFactory';\nimport type { PropertiesProvider } from './PfdnPropertiesProvider';\nimport { debounce, deepGet, deepSet, type Definition } from './utils';\n\n/** The side-tab registration surface the panel needs (structural). */\nexport interface SideTabRegistration {\n title?: string;\n iconClassName?: string;\n action: {\n created?: (content: HTMLElement | null) => void;\n [gesture: string]: ((content: HTMLElement | null) => void) | undefined;\n };\n}\nexport interface SideTabsRegistrar {\n registerSideTab(tab: SideTabRegistration, index?: number): void;\n}\n\n/** A selection entry as delivered by the core `selection.changed` event. */\ninterface SelectionEntry {\n definition: Definition;\n}\n\ninterface TrackedEntry {\n scope: EntryResource;\n definition: Definition;\n formNode: HTMLElement;\n}\n\n/** Parse an HTML fragment into its first element. */\nfunction fromHtml(html: string): HTMLElement {\n const template = document.createElement('template');\n template.innerHTML = html.trim();\n return template.content.firstElementChild as HTMLElement;\n}\n\nconst FORM_CONTROLS = new Set(['INPUT', 'TEXTAREA', 'SELECT']);\n\n/**\n * The editor properties panel: a tabbed editor for the selected element's\n * model properties. Ported from `@d3-polytree/properties-panel`'s\n * `PropertiesPanel.js`, de-jQuery-ed onto native DOM; the `scroll-tabs` widget\n * is replaced by native click-to-select tabs.\n */\nexport class PropertiesPanel {\n static readonly $inject = [\n 'sideTabsProvider',\n 'eventBus',\n 'propertiesProvider',\n 'd3polytree.definitions.settings'\n ];\n\n private readonly _eventBus: EventEmitter;\n private readonly _propertiesProvider: PropertiesProvider;\n private readonly _diagramSettings: Definition;\n private _entries: Record<string, TrackedEntry> = {};\n\n private _container: HTMLElement | null = null;\n private _tabsEl: HTMLElement | null = null;\n private _contentsEl: HTMLElement | null = null;\n\n constructor(\n sideTabsProvider: SideTabsRegistrar,\n eventBus: EventEmitter,\n propertiesProvider: PropertiesProvider,\n diagramSettings: Definition\n ) {\n this._eventBus = eventBus;\n this._propertiesProvider = propertiesProvider;\n this._diagramSettings = diagramSettings;\n this._registerSideTab(sideTabsProvider);\n this._registerSelectionListener();\n }\n\n private _registerSideTab(provider: SideTabsRegistrar): void {\n provider.registerSideTab(\n {\n title: 'Properties',\n iconClassName: 'icon-sliders',\n action: { created: (content) => this._drawPanel(content) }\n },\n 1\n );\n }\n\n private _registerSelectionListener(): void {\n this._eventBus.on(\n 'selection.changed',\n (oldSelection: SelectionEntry[], newSelection: SelectionEntry[]) => {\n let selected: Definition = this._diagramSettings;\n if (\n newSelection.length === 1 &&\n (oldSelection.length !== 1 ||\n oldSelection[0].definition.id !== newSelection[0].definition.id)\n ) {\n selected = newSelection[0].definition;\n }\n this._update(selected);\n }\n );\n }\n\n private _drawPanel(content: HTMLElement | null): void {\n if (!content) {\n return;\n }\n this._drawContainer(content);\n this._update(this._diagramSettings);\n }\n\n private _drawContainer(content: HTMLElement): void {\n this._container = fromHtml(PropertiesPanel.HTML_MARKUP);\n content.insertBefore(this._container, content.firstChild);\n this._tabsEl = this._container.querySelector('.tab-sheets');\n this._contentsEl = this._container.querySelector('.pfdjs-pp-contents');\n\n this._container.addEventListener('click', (event) => {\n const tab = (event.target as Element).closest<HTMLElement>('.tab-sheet');\n if (tab) {\n this._selectTab(tab.getAttribute('data-tab-target'));\n event.stopImmediatePropagation();\n }\n });\n this._registerInputChangeHandlers();\n }\n\n private _registerInputChangeHandlers(): void {\n const container = this._container;\n if (!container) {\n return;\n }\n // debounce keystroke updates on text inputs/areas; selects fire on change.\n const debouncedApply = debounce((target: HTMLElement) => this._applyChange(target), 300);\n container.addEventListener('input', (event) => {\n const target = event.target as HTMLElement;\n if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {\n debouncedApply(target);\n }\n });\n container.addEventListener('change', (event) => {\n const target = event.target as HTMLElement;\n if (FORM_CONTROLS.has(target.tagName)) {\n this._applyChange(target);\n }\n });\n this._eventBus.on(\n 'PropertiesPanel.propertyChanged',\n (propertyId: string, definition: Definition) => this._applyChangeByProperty(propertyId, definition)\n );\n }\n\n private _applyChange(target: HTMLElement): void {\n const entryId = target.getAttribute('name');\n if (!entryId) {\n return;\n }\n this._commit(entryId, (target as HTMLInputElement).value);\n }\n\n private _applyChangeByProperty(propertyId: string, definition: Definition): void {\n this._commit(propertyId, deepGet(definition, propertyId));\n }\n\n private _commit(entryId: string, newValue: unknown): void {\n const entry = this._entries[entryId];\n if (!entry) {\n return;\n }\n const props: Record<string, unknown> = {};\n deepSet(props, entryId, newValue);\n entry.scope.set(entry.definition, props);\n this._propertiesProvider.updateDrawing(entry.definition);\n }\n\n private _selectTab(tabId: string | null): void {\n this._tabsEl?.querySelectorAll<HTMLElement>('.tab-sheet').forEach((tab) => {\n tab.classList.toggle('tab-sheet-active', tab.getAttribute('data-tab-target') === tabId);\n });\n this._contentsEl?.querySelectorAll<HTMLElement>('.pfdjs-pp-content').forEach((content) => {\n content.classList.toggle('open', content.getAttribute('data-tab-target') === tabId);\n });\n }\n\n private _update(definition: Definition | undefined): void {\n if (this._tabsEl && this._contentsEl) {\n this._tabsEl.replaceChildren();\n this._contentsEl.replaceChildren();\n }\n if (definition) {\n this._drawEntries(definition);\n }\n }\n\n private _drawEntries(definition: Definition): void {\n if (!this._tabsEl || !this._contentsEl) {\n return;\n }\n const tabs = this._propertiesProvider.getTabs(definition);\n const renderedTabs: { id: string; label: string }[] = [];\n this._entries = {};\n\n for (const tab of tabs) {\n const content = fromHtml(`<div class=\"pfdjs-pp-content\" data-tab-target=\"${tab.id}\"></div>`);\n let tabHasContent = false;\n\n for (const group of tab.groups) {\n if (group.entries.length === 0) {\n continue;\n }\n const groupContent = fromHtml(\n `<div class=\"pfdjs-pp-content-group\" data-group-target=\"${group.id}\">` +\n `<div class=\"tab-content-group-title\">${group.label}</div></div>`\n );\n for (const entry of group.entries) {\n const entryNode = fromHtml(`<div>${entry.html}</div>`);\n groupContent.appendChild(entryNode);\n this._entries[entry.id] = { scope: entry, definition, formNode: entryNode };\n }\n content.appendChild(groupContent);\n tabHasContent = true;\n }\n\n if (tabHasContent) {\n this._contentsEl.appendChild(content);\n renderedTabs.push({ id: tab.id, label: tab.label });\n }\n }\n\n // populate each entry from the model\n Object.values(this._entries).forEach((entry) => entry.scope.get(entry.definition, entry.formNode));\n\n // draw the tab strip\n let firstTab: string | null = null;\n for (const tab of renderedTabs) {\n firstTab ??= tab.id;\n this._tabsEl.appendChild(\n fromHtml(\n `<li class=\"tab-sheet\" data-tab-target=\"${tab.id}\"><a href=\"#\">${tab.label}</a></li>`\n )\n );\n }\n this._selectTab(firstTab);\n }\n\n static readonly HTML_MARKUP =\n '<div id=\"pfdjs-pp-container\">' +\n '<div class=\"pfdjs-pp-tabs\"><ul class=\"tab-sheets\"></ul></div>' +\n '<div class=\"pfdjs-pp-contents\"></div>' +\n '</div>';\n}\n","/**\n * @d3-polytree/properties-panel — the editor's element-properties panel.\n *\n * Modernised (B6) from the 2017 jQuery/spectrum/scroll-tabs source to TypeScript\n * + ESM with native DOM: jQuery is gone, the colour entry uses a native\n * `<input type=\"color\">`, and the `scroll-tabs` widget is replaced by native\n * click-to-select tabs. Ships three didi modules (entry factory, PFDN provider,\n * panel) for the editor to compose.\n */\nexport { EntryFactory, entryFactoryModule } from './EntryFactory';\nexport type { EntryOptions, EntryResource, SelectOption } from './EntryFactory';\nexport {\n PfdnPropertiesProvider,\n pfdnPropertiesProviderModule\n} from './PfdnPropertiesProvider';\nexport type {\n IconMap,\n PropertiesGroup,\n PropertiesProvider,\n PropertiesTab\n} from './PfdnPropertiesProvider';\nexport { PropertiesPanel } from './PropertiesPanel';\nexport type { SideTabRegistration, SideTabsRegistrar } from './PropertiesPanel';\nexport type { Definition } from './utils';\n\nimport { PropertiesPanel } from './PropertiesPanel';\n\n/** didi module contributing the properties panel (composes with the provider). */\nexport const propertiesPanelModule = {\n __init__: ['propertiesPanel'],\n propertiesPanel: ['type', PropertiesPanel]\n};\n\nexport default propertiesPanelModule;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/properties-panel/utils.ts","../src/properties-panel/EntryFactory.ts","../src/properties-panel/PfdnPropertiesProvider.ts","../src/properties-panel/PropertiesPanel.ts","../src/properties-panel/index.ts"],"sourcesContent":["/**\n * @d3-polytree/editor — create and modify polytree diagrams.\n *\n * Extends the {@link InteractiveViewer} with the editing layer: element\n * dragging plus the modelling create/save/delete flows. Element creation is\n * exposed programmatically here; the palette toolbar UI is layered on next.\n */\nimport { InteractiveViewer, type InteractiveViewerOptions } from '@d3-polytree/interactive-viewer';\nimport { Viewer } from '@d3-polytree/viewer';\nimport {\n dragModule,\n modellingModule,\n exportingModule,\n localStorageModule,\n uploadModule,\n paletteModule,\n resizeElementModule,\n type DiagramModule,\n type DrawingRegistry,\n type ModellingModelElement,\n type CreateParameters,\n type CommandStack,\n type CreateContext,\n type Selection\n} from '@d3-polytree/core';\n// The properties panel used to be its own package; it is now folded in here\n// (the editor was its only consumer) and re-exported below.\nimport {\n entryFactoryModule,\n pfdnPropertiesProviderModule,\n propertiesPanelModule\n} from './properties-panel';\n\nexport * from './properties-panel';\n\n/** The document a fresh editor opens with. */\nconst INITIAL_DIAGRAM =\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>' +\n '<pfdn:diagram xmlns:pfdn=\"http://pfdn\" xmlns=\"http://pfdn\">' +\n '<settings author=\"No Author\" name=\"No Name Diagram\" status=\"1\">' +\n '<zoom><offset x=\"0\" y=\"0\" /><scale>1</scale></zoom><grid />' +\n '</settings>' +\n '<node id=\"node_1\" label=\"label_1\" status=\"1\"><position x=\"20\" y=\"100\" /></node>' +\n '<label id=\"label_1\" fontSize=\"12\" isReadOnly=\"true\" status=\"1\">' +\n '<position x=\"33\" y=\"140\" /><text>Node 1</text></label>' +\n '</pfdn:diagram>';\n\nexport type EditorOptions = InteractiveViewerOptions;\n\nexport class Editor extends InteractiveViewer {\n /** Editing modules on top of the interaction layer. */\n static readonly editionModules: readonly DiagramModule[] = [\n dragModule as DiagramModule,\n modellingModule as DiagramModule,\n exportingModule as DiagramModule,\n localStorageModule as DiagramModule,\n uploadModule as DiagramModule,\n paletteModule as DiagramModule,\n resizeElementModule as DiagramModule,\n // the properties panel (registers a side tab; side-tabs + search-panel are\n // inherited from InteractiveViewer)\n entryFactoryModule as DiagramModule,\n pfdnPropertiesProviderModule as DiagramModule,\n propertiesPanelModule as DiagramModule\n ];\n\n /** The document a fresh editor opens with (used by {@link createDiagram}). */\n initialDiagram = INITIAL_DIAGRAM;\n\n private readonly _onKeydown = (event: KeyboardEvent): void => this._handleKeydown(event);\n\n constructor(options: EditorOptions = {}) {\n super(options);\n // Keyboard undo/redo. Scoped to the editor container (greenfield — the\n // components had no keyboard handling); removed in destroy().\n options.container?.addEventListener('keydown', this._onKeydown);\n }\n\n private _handleKeydown(event: KeyboardEvent): void {\n // Never steal typing from a panel field.\n const target = event.target as HTMLElement | null;\n if (target && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA')) {\n return;\n }\n // Undo/redo only make sense once a document is open.\n if (!this.getHost()) {\n return;\n }\n const mod = event.ctrlKey || event.metaKey;\n if (!mod) {\n return;\n }\n const key = event.key.toLowerCase();\n if (key === 'z' && event.shiftKey) {\n event.preventDefault();\n this.redo();\n } else if (key === 'z') {\n event.preventDefault();\n this.undo();\n } else if (key === 'y') {\n event.preventDefault();\n this.redo();\n }\n }\n\n /** Tear down the editor, removing the keyboard binding. */\n destroy(): void {\n this.options.container?.removeEventListener('keydown', this._onKeydown);\n super.destroy();\n }\n\n /** (Re)open the initial diagram. */\n createDiagram(): Promise<void> {\n return this.importDiagram(this.initialDiagram);\n }\n\n getModules(): readonly DiagramModule[] {\n // interaction + editing features first (they subscribe / swap the layer),\n // then the drawers\n return [\n ...InteractiveViewer.interactionModules,\n ...Editor.editionModules,\n ...Viewer.modules\n ];\n }\n\n /**\n * Create a node (and its associated label) at an optional position.\n *\n * Routed through the command stack so it persists and is undoable (since B10\n * the draw-layer `.created` event no longer persists on its own).\n */\n createNode(parameters: CreateParameters = {}): ModellingModelElement {\n const ctx: CreateContext = { className: 'node', parameters: [parameters] };\n this.get<CommandStack>('commandStack').execute('element.create', ctx);\n return ctx.created as ModellingModelElement;\n }\n\n /** Select an element by definition (e.g. to prepare a delete). */\n select(definition: ModellingModelElement): void {\n const element = this.get<DrawingRegistry>('drawingRegistry').get(definition.id as string);\n if (element) {\n this.get<Selection>('selection').select(element, definition);\n }\n }\n\n /** Delete the current selection (cascading to associated labels). */\n deleteSelected(): void {\n this.get<Selection>('selection').deleteSelected();\n }\n\n /** Undo the last edit (a whole gesture is one step). No-op if nothing to undo. */\n undo(): void {\n this.get<CommandStack>('commandStack').undo();\n }\n\n /** Redo the last undone edit. No-op if nothing to redo. */\n redo(): void {\n this.get<CommandStack>('commandStack').redo();\n }\n\n /** Whether there is an edit to undo. */\n canUndo(): boolean {\n return this.get<CommandStack>('commandStack').canUndo();\n }\n\n /** Whether there is an undone edit to redo. */\n canRedo(): boolean {\n return this.get<CommandStack>('commandStack').canRedo();\n }\n}\n\nexport default Editor;\n","/** A moddle model element as read/written by the properties panel. */\nexport interface Definition {\n id?: string;\n label?: Definition;\n $instanceOf(type: string): boolean;\n get(property: string): unknown;\n [key: string]: unknown;\n}\n\n/** `definition.$instanceOf(elementType)` — ported from `utils/modelUtils`. */\nexport function is(definition: Definition, elementType: string): boolean {\n return definition.$instanceOf(elementType);\n}\n\n/** Read a dotted property path (`label.text`) by plain property access. */\nexport function deepGet(obj: unknown, path: string): unknown {\n return path\n .split('.')\n .reduce<unknown>(\n (o, k) => (o == null ? undefined : (o as Record<string, unknown>)[k]),\n obj\n );\n}\n\n/** Write a dotted property path, creating intermediate objects as needed. */\nexport function deepSet(obj: Record<string, unknown>, path: string, value: unknown): void {\n const keys = path.split('.');\n let cursor = obj;\n for (let i = 0; i < keys.length - 1; i += 1) {\n const key = keys[i];\n if (cursor[key] == null || typeof cursor[key] !== 'object') {\n cursor[key] = {};\n }\n cursor = cursor[key] as Record<string, unknown>;\n }\n cursor[keys[keys.length - 1]] = value;\n}\n\n/** Trailing-nothing leading-edge? No — trailing debounce, like lodash's default. */\nexport function debounce<A extends unknown[]>(\n fn: (...args: A) => void,\n wait: number\n): (...args: A) => void {\n let timer: ReturnType<typeof setTimeout> | undefined;\n return (...args: A) => {\n if (timer) {\n clearTimeout(timer);\n }\n timer = setTimeout(() => fn(...args), wait);\n };\n}\n\n/** Title-case a token (`lineColor` → `Line Color`, `aws-ec2` → `Aws Ec 2`). */\nexport function startCase(input: string): string {\n return input\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/([a-zA-Z])([0-9])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim()\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\n/** Whether a string is a `#rrggbb` colour (accepted by `<input type=color>`). */\nexport function isHexColor(value: unknown): value is string {\n return typeof value === 'string' && /^#[0-9a-fA-F]{6}$/.test(value);\n}\n","import type EventEmitter from 'eventemitter3';\nimport type { DiagramEventMap } from '@d3-polytree/core';\nimport { deepGet, deepSet, isHexColor, type Definition } from './utils';\n\n/** A `{name,value}` option for a select entry. */\nexport interface SelectOption {\n name: string;\n value: string;\n}\n\n/** Options accepted when building an entry. */\nexport interface EntryOptions {\n id: string;\n modelProperty: string;\n label?: string;\n description?: string;\n type?: string;\n allowEmpty?: boolean;\n selectOptions?: SelectOption[];\n}\n\n/** A rendered property entry: its markup plus get/set behaviour. */\nexport interface EntryResource extends EntryOptions {\n html: string;\n get: (element: Definition, formNode: HTMLElement) => void;\n set: (element: Definition, values: Record<string, unknown>) => boolean;\n validate: () => Record<string, unknown>;\n triggerUpdate: (propertyId: string, element: Definition) => void;\n}\n\nfunction ensureNotNull(prop: string | undefined): string {\n if (!prop) {\n throw new Error(`${prop} must be set.`);\n }\n return prop;\n}\n\n/**\n * Builds property-panel entries (text / select / colour / spreadsheet). Ported\n * from `@d3-polytree/properties-panel`'s `entryFactory/*`, de-jQuery-ed onto\n * native DOM; the colour entry uses a native `<input type=\"color\">` in place of\n * spectrum-colorpicker.\n */\nexport class EntryFactory {\n static readonly $inject = ['eventBus'];\n\n private readonly _eventBus: EventEmitter<DiagramEventMap>;\n\n constructor(eventBus: EventEmitter<DiagramEventMap>) {\n this._eventBus = eventBus;\n }\n\n setDefaultParameters(options: EntryOptions): EntryResource {\n const eventBus = this._eventBus;\n\n const defaultGet = (element: Definition, formNode: HTMLElement): void => {\n const prop = ensureNotNull(options.modelProperty);\n const value = deepGet(element, prop);\n const input = formNode.querySelector('input');\n if (input) {\n (input as HTMLInputElement).value = value == null ? '' : String(value);\n }\n };\n\n const defaultSet = (element: Definition, values: Record<string, unknown>): boolean => {\n const prop = ensureNotNull(options.modelProperty);\n deepSet(element as unknown as Record<string, unknown>, prop, deepGet(values, prop));\n return true;\n };\n\n const triggerUpdate = (propertyId: string, element: Definition): void => {\n eventBus.emit('PropertiesPanel.propertyChanged', propertyId, element);\n };\n\n return {\n html: '',\n description: '',\n get: defaultGet,\n set: defaultSet,\n validate: () => ({}),\n ...options,\n triggerUpdate\n };\n }\n\n textField(options: EntryOptions): EntryResource {\n return textInputField(this.setDefaultParameters(options));\n }\n\n selectBox(options: EntryOptions): EntryResource {\n return selectBoxField(this.setDefaultParameters(options));\n }\n\n colorPicker(options: EntryOptions): EntryResource {\n return colorPickerField(this.setDefaultParameters(options));\n }\n\n spreadsheet(options: EntryOptions): EntryResource {\n // Placeholder in the source engine; kept as an API-compatible no-op.\n return this.setDefaultParameters(options);\n }\n}\n\nfunction fieldWrapper(resource: EntryResource, inner: string): string {\n const label = resource.label ?? resource.id;\n return (\n `<div class=\"pfdjs-pp-field-wrapper\">` +\n `<label for=\"pfdjs-${resource.id}\">${label}</label>${inner}</div>`\n );\n}\n\nfunction textInputField(resource: EntryResource): EntryResource {\n const type = resource.type ?? 'text';\n resource.html = fieldWrapper(\n resource,\n `<input id=\"pfdjs-${resource.id}\" type=\"${type}\" name=\"${resource.modelProperty}\" />`\n );\n return resource;\n}\n\nfunction selectBoxField(resource: EntryResource): EntryResource {\n const allowEmpty = resource.allowEmpty ?? true;\n const options = Array.isArray(resource.selectOptions)\n ? resource.selectOptions.concat(allowEmpty ? [{ name: '', value: '' }] : [])\n : [{ name: '', value: '' }];\n\n const optionsHtml = options\n .map((o) => `<option value=\"${o.value}\">${o.name}</option>`)\n .join('');\n resource.html = fieldWrapper(\n resource,\n `<select id=\"pfdjs-${resource.id}\" name=\"${resource.modelProperty}\">${optionsHtml}</select>`\n );\n\n resource.get = (element, formNode) => {\n const value = element.get(resource.modelProperty) ?? 'default';\n formNode\n .querySelectorAll<HTMLOptionElement>(`select#pfdjs-${resource.id} > option`)\n .forEach((option) => {\n option.selected = option.value === value;\n });\n };\n\n return resource;\n}\n\nfunction colorPickerField(resource: EntryResource): EntryResource {\n resource.html = fieldWrapper(\n resource,\n `<input id=\"pfdjs-${resource.id}\" type=\"color\" name=\"${resource.modelProperty}\" />`\n );\n resource.get = (element, formNode) => {\n const input = formNode.querySelector<HTMLInputElement>('input[type=color]');\n const value = deepGet(element, resource.modelProperty);\n if (input && isHexColor(value)) {\n input.value = value;\n }\n };\n return resource;\n}\n\n/** didi module contributing the entry factory. */\nexport const entryFactoryModule = {\n __init__: ['entryFactory'],\n entryFactory: ['type', EntryFactory]\n};\n","import type EventEmitter from 'eventemitter3';\nimport type { DiagramEventMap } from '@d3-polytree/core';\nimport type { EntryFactory, EntryResource } from './EntryFactory';\nimport { is, startCase, type Definition } from './utils';\n\n/** A group of entries within a tab. */\nexport interface PropertiesGroup {\n id: string;\n label: string;\n entries: EntryResource[];\n}\n\n/** A properties-panel tab. */\nexport interface PropertiesTab {\n id: string;\n label: string;\n groups: PropertiesGroup[];\n}\n\n/** Icon registry token: icon type → SVG source. */\nexport type IconMap = Record<string, string>;\n\n/** A properties provider: supplies the tabs for a selected element. */\nexport interface PropertiesProvider {\n getTabs(element: Definition): PropertiesTab[];\n updateDrawing(definition: Definition): void;\n}\n\n// --- pfdn property parts (ported from provider/pfdn/tabs/parts/*) ------------\n\nfunction nameProps(group: PropertiesGroup, element: Definition, factory: EntryFactory): void {\n if (is(element, 'pfdn:Node')) {\n group.entries.push(factory.textField({ id: 'name', label: 'Name', modelProperty: 'name' }));\n group.entries.push(factory.textField({ id: 'tag', label: 'Tag', modelProperty: 'tag' }));\n group.entries.push(\n factory.textField({ id: 'label.text', label: 'Diagram label', modelProperty: 'label.text' })\n );\n } else if (is(element, 'pfdn:Settings')) {\n group.entries.push(factory.textField({ id: 'name', label: 'Diagram name', modelProperty: 'name' }));\n group.entries.push(factory.textField({ id: 'author', label: \"Author's name\", modelProperty: 'author' }));\n } else if (is(element, 'pfdn:Link')) {\n group.entries.push(\n factory.textField({ id: 'label.text', label: 'Diagram label', modelProperty: 'label.text' })\n );\n } else if (is(element, 'pfdn:Label')) {\n group.entries.push(factory.textField({ id: 'text', label: 'Label', modelProperty: 'text' }));\n }\n}\n\nfunction nodeFormatProps(\n group: PropertiesGroup,\n element: Definition,\n factory: EntryFactory,\n icons: IconMap\n): void {\n if (!is(element, 'pfdn:Node')) {\n return;\n }\n const selectOptions = Object.keys(icons).map((key) => ({ value: key, name: startCase(key) }));\n group.entries.push(\n factory.selectBox({\n id: 'type',\n label: 'Icon',\n modelProperty: 'type',\n allowEmpty: false,\n selectOptions\n })\n );\n group.entries.push(\n factory.textField({ id: 'size', label: 'Size', modelProperty: 'size', type: 'number' })\n );\n}\n\nfunction linkFormatProps(group: PropertiesGroup, element: Definition, factory: EntryFactory): void {\n if (!is(element, 'pfdn:Link')) {\n return;\n }\n group.entries.push(\n factory.textField({ id: 'lineWidth', label: 'Line width', modelProperty: 'lineWidth', type: 'number' })\n );\n group.entries.push(\n factory.colorPicker({ id: 'lineColor', label: 'Line color', modelProperty: 'lineColor' })\n );\n}\n\nfunction labelFormatProps(group: PropertiesGroup, element: Definition, factory: EntryFactory): void {\n if (is(element, 'pfdn:Node') || is(element, 'pfdn:Link')) {\n group.entries.push(\n factory.textField({\n id: 'label.fontSize',\n label: 'Font size',\n modelProperty: 'label.fontSize',\n type: 'number'\n })\n );\n group.entries.push(\n factory.colorPicker({ id: 'label.color', label: 'Color', modelProperty: 'label.color' })\n );\n } else if (is(element, 'pfdn:Label')) {\n group.entries.push(\n factory.textField({ id: 'fontSize', label: 'Font size', modelProperty: 'fontSize', type: 'number' })\n );\n group.entries.push(factory.colorPicker({ id: 'color', label: 'Color', modelProperty: 'color' }));\n }\n}\n\nfunction gridFormatProps(group: PropertiesGroup, element: Definition, factory: EntryFactory): void {\n if (!is(element, 'pfdn:Settings')) {\n return;\n }\n group.entries.push(\n factory.colorPicker({ id: 'backgroundColor', label: 'Background color', modelProperty: 'backgroundColor' })\n );\n group.entries.push(\n factory.colorPicker({ id: 'grid.lineColor', label: 'Line color', modelProperty: 'grid.lineColor' })\n );\n group.entries.push(\n factory.textField({ id: 'grid.size', label: 'Square size', modelProperty: 'grid.size', type: 'number' })\n );\n group.entries.push(\n factory.textField({ id: 'grid.lineWidth', label: 'Line width', modelProperty: 'grid.lineWidth', type: 'number' })\n );\n}\n\n/**\n * The PFDN properties provider: builds the Properties + Format tabs for the\n * selected element, and applies edits back to the drawing. Ported from\n * `provider/pfdn/*`.\n */\nexport class PfdnPropertiesProvider implements PropertiesProvider {\n static readonly $inject = ['icons', 'entryFactory', 'eventBus'];\n\n private readonly _icons: IconMap;\n private readonly _entryFactory: EntryFactory;\n private readonly _eventBus: EventEmitter<DiagramEventMap>;\n\n constructor(icons: IconMap, entryFactory: EntryFactory, eventBus: EventEmitter<DiagramEventMap>) {\n this._icons = icons;\n this._entryFactory = entryFactory;\n this._eventBus = eventBus;\n }\n\n updateDrawing(definition: Definition): void {\n if (is(definition, 'pfdn:Settings')) {\n this._eventBus.emit('canvas.resized');\n return;\n }\n this._eventBus.emit('element.updated', definition.id!, definition);\n if (is(definition, 'pfdn:Link') || is(definition, 'pfdn:Node')) {\n const label = definition.label;\n if (label) {\n this._eventBus.emit('element.updated', label.id!, label);\n }\n }\n }\n\n getTabs(element: Definition): PropertiesTab[] {\n const factory = this._entryFactory;\n return [this._propertiesTab(element, factory), this._formatTab(element, factory)];\n }\n\n private _propertiesTab(element: Definition, factory: EntryFactory): PropertiesTab {\n const general: PropertiesGroup = { id: 'general', label: 'General', entries: [] };\n nameProps(general, element, factory);\n return { id: 'properties', label: 'Properties', groups: [general] };\n }\n\n private _formatTab(element: Definition, factory: EntryFactory): PropertiesTab {\n const elementFormat: PropertiesGroup = { id: 'elementFormat', label: 'Element format', entries: [] };\n const labelFormat: PropertiesGroup = { id: 'labelFormat', label: 'Label format', entries: [] };\n const gridFormat: PropertiesGroup = { id: 'gridFormat', label: 'Grid format', entries: [] };\n\n nodeFormatProps(elementFormat, element, factory, this._icons);\n linkFormatProps(elementFormat, element, factory);\n labelFormatProps(labelFormat, element, factory);\n gridFormatProps(gridFormat, element, factory);\n\n return { id: 'format', label: 'Format', groups: [elementFormat, labelFormat, gridFormat] };\n }\n}\n\n/** didi module contributing the PFDN properties provider. */\nexport const pfdnPropertiesProviderModule = {\n __init__: ['propertiesProvider'],\n propertiesProvider: ['type', PfdnPropertiesProvider]\n};\n","import type EventEmitter from 'eventemitter3';\nimport type { DiagramEventMap } from '@d3-polytree/core';\nimport type { CommandStack, CommandContext } from '@d3-polytree/core';\nimport type { EntryResource } from './EntryFactory';\nimport type { PropertiesProvider } from './PfdnPropertiesProvider';\nimport { debounce, deepGet, deepSet, type Definition } from './utils';\n\n/** The memento for an `element.updateProperties` command. */\ninterface UpdatePropsContext extends CommandContext {\n scope: EntryResource;\n definition: Definition;\n before: Record<string, unknown>;\n after: Record<string, unknown>;\n}\n\n/** The side-tab registration surface the panel needs (structural). */\nexport interface SideTabRegistration {\n title?: string;\n iconClassName?: string;\n action: {\n created?: (content: HTMLElement | null) => void;\n [gesture: string]: ((content: HTMLElement | null) => void) | undefined;\n };\n}\nexport interface SideTabsRegistrar {\n registerSideTab(tab: SideTabRegistration, index?: number): void;\n}\n\n/** A selection entry as delivered by the core `selection.changed` event. */\ninterface SelectionEntry {\n definition: Definition;\n}\n\ninterface TrackedEntry {\n scope: EntryResource;\n definition: Definition;\n formNode: HTMLElement;\n}\n\n/** Parse an HTML fragment into its first element. */\nfunction fromHtml(html: string): HTMLElement {\n const template = document.createElement('template');\n template.innerHTML = html.trim();\n return template.content.firstElementChild as HTMLElement;\n}\n\nconst FORM_CONTROLS = new Set(['INPUT', 'TEXTAREA', 'SELECT']);\n\n/**\n * The editor properties panel: a tabbed editor for the selected element's\n * model properties. Ported from `@d3-polytree/properties-panel`'s\n * `PropertiesPanel.js`, de-jQuery-ed onto native DOM; the `scroll-tabs` widget\n * is replaced by native click-to-select tabs.\n */\nexport class PropertiesPanel {\n static readonly $inject = [\n 'sideTabsProvider',\n 'eventBus',\n 'propertiesProvider',\n 'd3polytree.definitions.settings',\n 'commandStack'\n ];\n\n private readonly _eventBus: EventEmitter<DiagramEventMap>;\n private readonly _propertiesProvider: PropertiesProvider;\n private readonly _diagramSettings: Definition;\n private readonly _commandStack: CommandStack;\n private _entries: Record<string, TrackedEntry> = {};\n\n private _container: HTMLElement | null = null;\n private _tabsEl: HTMLElement | null = null;\n private _contentsEl: HTMLElement | null = null;\n\n constructor(\n sideTabsProvider: SideTabsRegistrar,\n eventBus: EventEmitter<DiagramEventMap>,\n propertiesProvider: PropertiesProvider,\n diagramSettings: Definition,\n commandStack: CommandStack\n ) {\n this._eventBus = eventBus;\n this._propertiesProvider = propertiesProvider;\n this._diagramSettings = diagramSettings;\n this._commandStack = commandStack;\n this._registerUpdatePropertiesCommand();\n this._registerSideTab(sideTabsProvider);\n this._registerSelectionListener();\n }\n\n /**\n * Register the `element.updateProperties` command. Its apply logic is\n * editor-specific (a property `scope` plus the provider's drawing update), so\n * the panel — which owns both — registers it on the shared stack rather than\n * the core modelling orchestrator.\n */\n private _registerUpdatePropertiesCommand(): void {\n const apply = (ctx: UpdatePropsContext, props: Record<string, unknown>): void => {\n ctx.scope.set(ctx.definition, props);\n this._propertiesProvider.updateDrawing(ctx.definition);\n };\n this._commandStack.registerHandler('element.updateProperties', {\n execute: (ctx) => apply(ctx as UpdatePropsContext, (ctx as UpdatePropsContext).after),\n revert: (ctx) => apply(ctx as UpdatePropsContext, (ctx as UpdatePropsContext).before)\n });\n }\n\n private _registerSideTab(provider: SideTabsRegistrar): void {\n provider.registerSideTab(\n {\n title: 'Properties',\n iconClassName: 'icon-sliders',\n action: { created: (content) => this._drawPanel(content) }\n },\n 1\n );\n }\n\n private _registerSelectionListener(): void {\n this._eventBus.on(\n 'selection.changed',\n (oldSelection: SelectionEntry[], newSelection: SelectionEntry[]) => {\n let selected: Definition = this._diagramSettings;\n if (\n newSelection.length === 1 &&\n (oldSelection.length !== 1 ||\n oldSelection[0].definition.id !== newSelection[0].definition.id)\n ) {\n selected = newSelection[0].definition;\n }\n this._update(selected);\n }\n );\n }\n\n private _drawPanel(content: HTMLElement | null): void {\n if (!content) {\n return;\n }\n this._drawContainer(content);\n this._update(this._diagramSettings);\n }\n\n private _drawContainer(content: HTMLElement): void {\n this._container = fromHtml(PropertiesPanel.HTML_MARKUP);\n content.insertBefore(this._container, content.firstChild);\n this._tabsEl = this._container.querySelector('.tab-sheets');\n this._contentsEl = this._container.querySelector('.pfdjs-pp-contents');\n\n this._container.addEventListener('click', (event) => {\n const tab = (event.target as Element).closest<HTMLElement>('.tab-sheet');\n if (tab) {\n this._selectTab(tab.getAttribute('data-tab-target'));\n event.stopImmediatePropagation();\n }\n });\n this._registerInputChangeHandlers();\n }\n\n private _registerInputChangeHandlers(): void {\n const container = this._container;\n if (!container) {\n return;\n }\n // debounce keystroke updates on text inputs/areas; selects fire on change.\n const debouncedApply = debounce((target: HTMLElement) => this._applyChange(target), 300);\n container.addEventListener('input', (event) => {\n const target = event.target as HTMLElement;\n if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {\n debouncedApply(target);\n }\n });\n container.addEventListener('change', (event) => {\n const target = event.target as HTMLElement;\n if (FORM_CONTROLS.has(target.tagName)) {\n this._applyChange(target);\n }\n });\n this._eventBus.on(\n 'PropertiesPanel.propertyChanged',\n (propertyId: string, definition: Definition) => this._applyChangeByProperty(propertyId, definition)\n );\n }\n\n private _applyChange(target: HTMLElement): void {\n const entryId = target.getAttribute('name');\n if (!entryId) {\n return;\n }\n this._commit(entryId, (target as HTMLInputElement).value);\n }\n\n private _applyChangeByProperty(propertyId: string, definition: Definition): void {\n this._commit(propertyId, deepGet(definition, propertyId));\n }\n\n private _commit(entryId: string, newValue: unknown): void {\n const entry = this._entries[entryId];\n if (!entry) {\n return;\n }\n const after: Record<string, unknown> = {};\n deepSet(after, entryId, newValue);\n // Capture the prior value of the same path so the edit is undoable.\n const before: Record<string, unknown> = {};\n deepSet(before, entryId, deepGet(entry.definition, entryId));\n this._commandStack.execute('element.updateProperties', {\n scope: entry.scope,\n definition: entry.definition,\n before,\n after\n } satisfies UpdatePropsContext);\n }\n\n private _selectTab(tabId: string | null): void {\n this._tabsEl?.querySelectorAll<HTMLElement>('.tab-sheet').forEach((tab) => {\n tab.classList.toggle('tab-sheet-active', tab.getAttribute('data-tab-target') === tabId);\n });\n this._contentsEl?.querySelectorAll<HTMLElement>('.pfdjs-pp-content').forEach((content) => {\n content.classList.toggle('open', content.getAttribute('data-tab-target') === tabId);\n });\n }\n\n private _update(definition: Definition | undefined): void {\n if (this._tabsEl && this._contentsEl) {\n this._tabsEl.replaceChildren();\n this._contentsEl.replaceChildren();\n }\n if (definition) {\n this._drawEntries(definition);\n }\n }\n\n private _drawEntries(definition: Definition): void {\n if (!this._tabsEl || !this._contentsEl) {\n return;\n }\n const tabs = this._propertiesProvider.getTabs(definition);\n const renderedTabs: { id: string; label: string }[] = [];\n this._entries = {};\n\n for (const tab of tabs) {\n const content = fromHtml(`<div class=\"pfdjs-pp-content\" data-tab-target=\"${tab.id}\"></div>`);\n let tabHasContent = false;\n\n for (const group of tab.groups) {\n if (group.entries.length === 0) {\n continue;\n }\n const groupContent = fromHtml(\n `<div class=\"pfdjs-pp-content-group\" data-group-target=\"${group.id}\">` +\n `<div class=\"tab-content-group-title\">${group.label}</div></div>`\n );\n for (const entry of group.entries) {\n const entryNode = fromHtml(`<div>${entry.html}</div>`);\n groupContent.appendChild(entryNode);\n this._entries[entry.id] = { scope: entry, definition, formNode: entryNode };\n }\n content.appendChild(groupContent);\n tabHasContent = true;\n }\n\n if (tabHasContent) {\n this._contentsEl.appendChild(content);\n renderedTabs.push({ id: tab.id, label: tab.label });\n }\n }\n\n // populate each entry from the model\n Object.values(this._entries).forEach((entry) => entry.scope.get(entry.definition, entry.formNode));\n\n // draw the tab strip\n let firstTab: string | null = null;\n for (const tab of renderedTabs) {\n firstTab ??= tab.id;\n this._tabsEl.appendChild(\n fromHtml(\n `<li class=\"tab-sheet\" data-tab-target=\"${tab.id}\"><a href=\"#\">${tab.label}</a></li>`\n )\n );\n }\n this._selectTab(firstTab);\n }\n\n static readonly HTML_MARKUP =\n '<div id=\"pfdjs-pp-container\">' +\n '<div class=\"pfdjs-pp-tabs\"><ul class=\"tab-sheets\"></ul></div>' +\n '<div class=\"pfdjs-pp-contents\"></div>' +\n '</div>';\n}\n","/**\n * @d3-polytree/properties-panel — the editor's element-properties panel.\n *\n * Modernised (B6) from the 2017 jQuery/spectrum/scroll-tabs source to TypeScript\n * + ESM with native DOM: jQuery is gone, the colour entry uses a native\n * `<input type=\"color\">`, and the `scroll-tabs` widget is replaced by native\n * click-to-select tabs. Ships three didi modules (entry factory, PFDN provider,\n * panel) for the editor to compose.\n */\nexport { EntryFactory, entryFactoryModule } from './EntryFactory';\nexport type { EntryOptions, EntryResource, SelectOption } from './EntryFactory';\nexport {\n PfdnPropertiesProvider,\n pfdnPropertiesProviderModule\n} from './PfdnPropertiesProvider';\nexport type {\n IconMap,\n PropertiesGroup,\n PropertiesProvider,\n PropertiesTab\n} from './PfdnPropertiesProvider';\nexport { PropertiesPanel } from './PropertiesPanel';\nexport type { SideTabRegistration, SideTabsRegistrar } from './PropertiesPanel';\nexport type { Definition } from './utils';\n\nimport { PropertiesPanel } from './PropertiesPanel';\n\n/** didi module contributing the properties panel (composes with the provider). */\nexport const propertiesPanelModule = {\n __init__: ['propertiesPanel'],\n propertiesPanel: ['type', PropertiesPanel]\n};\n\nexport default propertiesPanelModule;\n"],"mappings":";AAOA,SAAS,yBAAwD;AACjE,SAAS,cAAc;AACvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAQK;;;ACdA,SAAS,GAAG,YAAwB,aAA8B;AACvE,SAAO,WAAW,YAAY,WAAW;AAC3C;AAGO,SAAS,QAAQ,KAAc,MAAuB;AAC3D,SAAO,KACJ,MAAM,GAAG,EACT;AAAA,IACC,CAAC,GAAG,MAAO,KAAK,OAAO,SAAa,EAA8B,CAAC;AAAA,IACnE;AAAA,EACF;AACJ;AAGO,SAAS,QAAQ,KAA8B,MAAc,OAAsB;AACxF,QAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,KAAK,SAAS,GAAG,KAAK,GAAG;AAC3C,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,OAAO,GAAG,KAAK,QAAQ,OAAO,OAAO,GAAG,MAAM,UAAU;AAC1D,aAAO,GAAG,IAAI,CAAC;AAAA,IACjB;AACA,aAAS,OAAO,GAAG;AAAA,EACrB;AACA,SAAO,KAAK,KAAK,SAAS,CAAC,CAAC,IAAI;AAClC;AAGO,SAAS,SACd,IACA,MACsB;AACtB,MAAI;AACJ,SAAO,IAAI,SAAY;AACrB,QAAI,OAAO;AACT,mBAAa,KAAK;AAAA,IACpB;AACA,YAAQ,WAAW,MAAM,GAAG,GAAG,IAAI,GAAG,IAAI;AAAA,EAC5C;AACF;AAGO,SAAS,UAAU,OAAuB;AAC/C,SAAO,MACJ,QAAQ,sBAAsB,OAAO,EACrC,QAAQ,sBAAsB,OAAO,EACrC,QAAQ,UAAU,GAAG,EACrB,QAAQ,QAAQ,GAAG,EACnB,KAAK,EACL,QAAQ,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC;AAC5C;AAGO,SAAS,WAAW,OAAiC;AAC1D,SAAO,OAAO,UAAU,YAAY,oBAAoB,KAAK,KAAK;AACpE;;;ACpCA,SAAS,cAAc,MAAkC;AACvD,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,GAAG,IAAI,eAAe;AAAA,EACxC;AACA,SAAO;AACT;AAQO,IAAM,eAAN,MAAmB;AAAA,EAKxB,YAAY,UAAyC;AACnD,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,qBAAqB,SAAsC;AACzD,UAAM,WAAW,KAAK;AAEtB,UAAM,aAAa,CAAC,SAAqB,aAAgC;AACvE,YAAM,OAAO,cAAc,QAAQ,aAAa;AAChD,YAAM,QAAQ,QAAQ,SAAS,IAAI;AACnC,YAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAI,OAAO;AACT,QAAC,MAA2B,QAAQ,SAAS,OAAO,KAAK,OAAO,KAAK;AAAA,MACvE;AAAA,IACF;AAEA,UAAM,aAAa,CAAC,SAAqB,WAA6C;AACpF,YAAM,OAAO,cAAc,QAAQ,aAAa;AAChD,cAAQ,SAA+C,MAAM,QAAQ,QAAQ,IAAI,CAAC;AAClF,aAAO;AAAA,IACT;AAEA,UAAM,gBAAgB,CAAC,YAAoB,YAA8B;AACvE,eAAS,KAAK,mCAAmC,YAAY,OAAO;AAAA,IACtE;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,aAAa;AAAA,MACb,KAAK;AAAA,MACL,KAAK;AAAA,MACL,UAAU,OAAO,CAAC;AAAA,MAClB,GAAG;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEA,UAAU,SAAsC;AAC9C,WAAO,eAAe,KAAK,qBAAqB,OAAO,CAAC;AAAA,EAC1D;AAAA,EAEA,UAAU,SAAsC;AAC9C,WAAO,eAAe,KAAK,qBAAqB,OAAO,CAAC;AAAA,EAC1D;AAAA,EAEA,YAAY,SAAsC;AAChD,WAAO,iBAAiB,KAAK,qBAAqB,OAAO,CAAC;AAAA,EAC5D;AAAA,EAEA,YAAY,SAAsC;AAEhD,WAAO,KAAK,qBAAqB,OAAO;AAAA,EAC1C;AACF;AA1Da,aACK,UAAU,CAAC,UAAU;AA2DvC,SAAS,aAAa,UAAyB,OAAuB;AACpE,QAAM,QAAQ,SAAS,SAAS,SAAS;AACzC,SACE,yDACqB,SAAS,EAAE,KAAK,KAAK,WAAW,KAAK;AAE9D;AAEA,SAAS,eAAe,UAAwC;AAC9D,QAAM,OAAO,SAAS,QAAQ;AAC9B,WAAS,OAAO;AAAA,IACd;AAAA,IACA,oBAAoB,SAAS,EAAE,WAAW,IAAI,WAAW,SAAS,aAAa;AAAA,EACjF;AACA,SAAO;AACT;AAEA,SAAS,eAAe,UAAwC;AAC9D,QAAM,aAAa,SAAS,cAAc;AAC1C,QAAM,UAAU,MAAM,QAAQ,SAAS,aAAa,IAChD,SAAS,cAAc,OAAO,aAAa,CAAC,EAAE,MAAM,IAAI,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,IACzE,CAAC,EAAE,MAAM,IAAI,OAAO,GAAG,CAAC;AAE5B,QAAM,cAAc,QACjB,IAAI,CAAC,MAAM,kBAAkB,EAAE,KAAK,KAAK,EAAE,IAAI,WAAW,EAC1D,KAAK,EAAE;AACV,WAAS,OAAO;AAAA,IACd;AAAA,IACA,qBAAqB,SAAS,EAAE,WAAW,SAAS,aAAa,KAAK,WAAW;AAAA,EACnF;AAEA,WAAS,MAAM,CAAC,SAAS,aAAa;AACpC,UAAM,QAAQ,QAAQ,IAAI,SAAS,aAAa,KAAK;AACrD,aACG,iBAAoC,gBAAgB,SAAS,EAAE,WAAW,EAC1E,QAAQ,CAAC,WAAW;AACnB,aAAO,WAAW,OAAO,UAAU;AAAA,IACrC,CAAC;AAAA,EACL;AAEA,SAAO;AACT;AAEA,SAAS,iBAAiB,UAAwC;AAChE,WAAS,OAAO;AAAA,IACd;AAAA,IACA,oBAAoB,SAAS,EAAE,wBAAwB,SAAS,aAAa;AAAA,EAC/E;AACA,WAAS,MAAM,CAAC,SAAS,aAAa;AACpC,UAAM,QAAQ,SAAS,cAAgC,mBAAmB;AAC1E,UAAM,QAAQ,QAAQ,SAAS,SAAS,aAAa;AACrD,QAAI,SAAS,WAAW,KAAK,GAAG;AAC9B,YAAM,QAAQ;AAAA,IAChB;AAAA,EACF;AACA,SAAO;AACT;AAGO,IAAM,qBAAqB;AAAA,EAChC,UAAU,CAAC,cAAc;AAAA,EACzB,cAAc,CAAC,QAAQ,YAAY;AACrC;;;ACvIA,SAAS,UAAU,OAAwB,SAAqB,SAA6B;AAC3F,MAAI,GAAG,SAAS,WAAW,GAAG;AAC5B,UAAM,QAAQ,KAAK,QAAQ,UAAU,EAAE,IAAI,QAAQ,OAAO,QAAQ,eAAe,OAAO,CAAC,CAAC;AAC1F,UAAM,QAAQ,KAAK,QAAQ,UAAU,EAAE,IAAI,OAAO,OAAO,OAAO,eAAe,MAAM,CAAC,CAAC;AACvF,UAAM,QAAQ;AAAA,MACZ,QAAQ,UAAU,EAAE,IAAI,cAAc,OAAO,iBAAiB,eAAe,aAAa,CAAC;AAAA,IAC7F;AAAA,EACF,WAAW,GAAG,SAAS,eAAe,GAAG;AACvC,UAAM,QAAQ,KAAK,QAAQ,UAAU,EAAE,IAAI,QAAQ,OAAO,gBAAgB,eAAe,OAAO,CAAC,CAAC;AAClG,UAAM,QAAQ,KAAK,QAAQ,UAAU,EAAE,IAAI,UAAU,OAAO,iBAAiB,eAAe,SAAS,CAAC,CAAC;AAAA,EACzG,WAAW,GAAG,SAAS,WAAW,GAAG;AACnC,UAAM,QAAQ;AAAA,MACZ,QAAQ,UAAU,EAAE,IAAI,cAAc,OAAO,iBAAiB,eAAe,aAAa,CAAC;AAAA,IAC7F;AAAA,EACF,WAAW,GAAG,SAAS,YAAY,GAAG;AACpC,UAAM,QAAQ,KAAK,QAAQ,UAAU,EAAE,IAAI,QAAQ,OAAO,SAAS,eAAe,OAAO,CAAC,CAAC;AAAA,EAC7F;AACF;AAEA,SAAS,gBACP,OACA,SACA,SACA,OACM;AACN,MAAI,CAAC,GAAG,SAAS,WAAW,GAAG;AAC7B;AAAA,EACF;AACA,QAAM,gBAAgB,OAAO,KAAK,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,KAAK,MAAM,UAAU,GAAG,EAAE,EAAE;AAC5F,QAAM,QAAQ;AAAA,IACZ,QAAQ,UAAU;AAAA,MAChB,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,eAAe;AAAA,MACf,YAAY;AAAA,MACZ;AAAA,IACF,CAAC;AAAA,EACH;AACA,QAAM,QAAQ;AAAA,IACZ,QAAQ,UAAU,EAAE,IAAI,QAAQ,OAAO,QAAQ,eAAe,QAAQ,MAAM,SAAS,CAAC;AAAA,EACxF;AACF;AAEA,SAAS,gBAAgB,OAAwB,SAAqB,SAA6B;AACjG,MAAI,CAAC,GAAG,SAAS,WAAW,GAAG;AAC7B;AAAA,EACF;AACA,QAAM,QAAQ;AAAA,IACZ,QAAQ,UAAU,EAAE,IAAI,aAAa,OAAO,cAAc,eAAe,aAAa,MAAM,SAAS,CAAC;AAAA,EACxG;AACA,QAAM,QAAQ;AAAA,IACZ,QAAQ,YAAY,EAAE,IAAI,aAAa,OAAO,cAAc,eAAe,YAAY,CAAC;AAAA,EAC1F;AACF;AAEA,SAAS,iBAAiB,OAAwB,SAAqB,SAA6B;AAClG,MAAI,GAAG,SAAS,WAAW,KAAK,GAAG,SAAS,WAAW,GAAG;AACxD,UAAM,QAAQ;AAAA,MACZ,QAAQ,UAAU;AAAA,QAChB,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,eAAe;AAAA,QACf,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AACA,UAAM,QAAQ;AAAA,MACZ,QAAQ,YAAY,EAAE,IAAI,eAAe,OAAO,SAAS,eAAe,cAAc,CAAC;AAAA,IACzF;AAAA,EACF,WAAW,GAAG,SAAS,YAAY,GAAG;AACpC,UAAM,QAAQ;AAAA,MACZ,QAAQ,UAAU,EAAE,IAAI,YAAY,OAAO,aAAa,eAAe,YAAY,MAAM,SAAS,CAAC;AAAA,IACrG;AACA,UAAM,QAAQ,KAAK,QAAQ,YAAY,EAAE,IAAI,SAAS,OAAO,SAAS,eAAe,QAAQ,CAAC,CAAC;AAAA,EACjG;AACF;AAEA,SAAS,gBAAgB,OAAwB,SAAqB,SAA6B;AACjG,MAAI,CAAC,GAAG,SAAS,eAAe,GAAG;AACjC;AAAA,EACF;AACA,QAAM,QAAQ;AAAA,IACZ,QAAQ,YAAY,EAAE,IAAI,mBAAmB,OAAO,oBAAoB,eAAe,kBAAkB,CAAC;AAAA,EAC5G;AACA,QAAM,QAAQ;AAAA,IACZ,QAAQ,YAAY,EAAE,IAAI,kBAAkB,OAAO,cAAc,eAAe,iBAAiB,CAAC;AAAA,EACpG;AACA,QAAM,QAAQ;AAAA,IACZ,QAAQ,UAAU,EAAE,IAAI,aAAa,OAAO,eAAe,eAAe,aAAa,MAAM,SAAS,CAAC;AAAA,EACzG;AACA,QAAM,QAAQ;AAAA,IACZ,QAAQ,UAAU,EAAE,IAAI,kBAAkB,OAAO,cAAc,eAAe,kBAAkB,MAAM,SAAS,CAAC;AAAA,EAClH;AACF;AAOO,IAAM,yBAAN,MAA2D;AAAA,EAOhE,YAAY,OAAgB,cAA4B,UAAyC;AAC/F,SAAK,SAAS;AACd,SAAK,gBAAgB;AACrB,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,cAAc,YAA8B;AAC1C,QAAI,GAAG,YAAY,eAAe,GAAG;AACnC,WAAK,UAAU,KAAK,gBAAgB;AACpC;AAAA,IACF;AACA,SAAK,UAAU,KAAK,mBAAmB,WAAW,IAAK,UAAU;AACjE,QAAI,GAAG,YAAY,WAAW,KAAK,GAAG,YAAY,WAAW,GAAG;AAC9D,YAAM,QAAQ,WAAW;AACzB,UAAI,OAAO;AACT,aAAK,UAAU,KAAK,mBAAmB,MAAM,IAAK,KAAK;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,QAAQ,SAAsC;AAC5C,UAAM,UAAU,KAAK;AACrB,WAAO,CAAC,KAAK,eAAe,SAAS,OAAO,GAAG,KAAK,WAAW,SAAS,OAAO,CAAC;AAAA,EAClF;AAAA,EAEQ,eAAe,SAAqB,SAAsC;AAChF,UAAM,UAA2B,EAAE,IAAI,WAAW,OAAO,WAAW,SAAS,CAAC,EAAE;AAChF,cAAU,SAAS,SAAS,OAAO;AACnC,WAAO,EAAE,IAAI,cAAc,OAAO,cAAc,QAAQ,CAAC,OAAO,EAAE;AAAA,EACpE;AAAA,EAEQ,WAAW,SAAqB,SAAsC;AAC5E,UAAM,gBAAiC,EAAE,IAAI,iBAAiB,OAAO,kBAAkB,SAAS,CAAC,EAAE;AACnG,UAAM,cAA+B,EAAE,IAAI,eAAe,OAAO,gBAAgB,SAAS,CAAC,EAAE;AAC7F,UAAM,aAA8B,EAAE,IAAI,cAAc,OAAO,eAAe,SAAS,CAAC,EAAE;AAE1F,oBAAgB,eAAe,SAAS,SAAS,KAAK,MAAM;AAC5D,oBAAgB,eAAe,SAAS,OAAO;AAC/C,qBAAiB,aAAa,SAAS,OAAO;AAC9C,oBAAgB,YAAY,SAAS,OAAO;AAE5C,WAAO,EAAE,IAAI,UAAU,OAAO,UAAU,QAAQ,CAAC,eAAe,aAAa,UAAU,EAAE;AAAA,EAC3F;AACF;AAlDa,uBACK,UAAU,CAAC,SAAS,gBAAgB,UAAU;AAoDzD,IAAM,+BAA+B;AAAA,EAC1C,UAAU,CAAC,oBAAoB;AAAA,EAC/B,oBAAoB,CAAC,QAAQ,sBAAsB;AACrD;;;ACjJA,SAAS,SAAS,MAA2B;AAC3C,QAAM,WAAW,SAAS,cAAc,UAAU;AAClD,WAAS,YAAY,KAAK,KAAK;AAC/B,SAAO,SAAS,QAAQ;AAC1B;AAEA,IAAM,gBAAgB,oBAAI,IAAI,CAAC,SAAS,YAAY,QAAQ,CAAC;AAQtD,IAAM,mBAAN,MAAM,iBAAgB;AAAA,EAmB3B,YACE,kBACA,UACA,oBACA,iBACA,cACA;AAZF,SAAQ,WAAyC,CAAC;AAElD,SAAQ,aAAiC;AACzC,SAAQ,UAA8B;AACtC,SAAQ,cAAkC;AASxC,SAAK,YAAY;AACjB,SAAK,sBAAsB;AAC3B,SAAK,mBAAmB;AACxB,SAAK,gBAAgB;AACrB,SAAK,iCAAiC;AACtC,SAAK,iBAAiB,gBAAgB;AACtC,SAAK,2BAA2B;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,mCAAyC;AAC/C,UAAM,QAAQ,CAAC,KAAyB,UAAyC;AAC/E,UAAI,MAAM,IAAI,IAAI,YAAY,KAAK;AACnC,WAAK,oBAAoB,cAAc,IAAI,UAAU;AAAA,IACvD;AACA,SAAK,cAAc,gBAAgB,4BAA4B;AAAA,MAC7D,SAAS,CAAC,QAAQ,MAAM,KAA4B,IAA2B,KAAK;AAAA,MACpF,QAAQ,CAAC,QAAQ,MAAM,KAA4B,IAA2B,MAAM;AAAA,IACtF,CAAC;AAAA,EACH;AAAA,EAEQ,iBAAiB,UAAmC;AAC1D,aAAS;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,eAAe;AAAA,QACf,QAAQ,EAAE,SAAS,CAAC,YAAY,KAAK,WAAW,OAAO,EAAE;AAAA,MAC3D;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,6BAAmC;AACzC,SAAK,UAAU;AAAA,MACb;AAAA,MACA,CAAC,cAAgC,iBAAmC;AAClE,YAAI,WAAuB,KAAK;AAChC,YACE,aAAa,WAAW,MACvB,aAAa,WAAW,KACvB,aAAa,CAAC,EAAE,WAAW,OAAO,aAAa,CAAC,EAAE,WAAW,KAC/D;AACA,qBAAW,aAAa,CAAC,EAAE;AAAA,QAC7B;AACA,aAAK,QAAQ,QAAQ;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,WAAW,SAAmC;AACpD,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AACA,SAAK,eAAe,OAAO;AAC3B,SAAK,QAAQ,KAAK,gBAAgB;AAAA,EACpC;AAAA,EAEQ,eAAe,SAA4B;AACjD,SAAK,aAAa,SAAS,iBAAgB,WAAW;AACtD,YAAQ,aAAa,KAAK,YAAY,QAAQ,UAAU;AACxD,SAAK,UAAU,KAAK,WAAW,cAAc,aAAa;AAC1D,SAAK,cAAc,KAAK,WAAW,cAAc,oBAAoB;AAErE,SAAK,WAAW,iBAAiB,SAAS,CAAC,UAAU;AACnD,YAAM,MAAO,MAAM,OAAmB,QAAqB,YAAY;AACvE,UAAI,KAAK;AACP,aAAK,WAAW,IAAI,aAAa,iBAAiB,CAAC;AACnD,cAAM,yBAAyB;AAAA,MACjC;AAAA,IACF,CAAC;AACD,SAAK,6BAA6B;AAAA,EACpC;AAAA,EAEQ,+BAAqC;AAC3C,UAAM,YAAY,KAAK;AACvB,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AAEA,UAAM,iBAAiB,SAAS,CAAC,WAAwB,KAAK,aAAa,MAAM,GAAG,GAAG;AACvF,cAAU,iBAAiB,SAAS,CAAC,UAAU;AAC7C,YAAM,SAAS,MAAM;AACrB,UAAI,OAAO,YAAY,WAAW,OAAO,YAAY,YAAY;AAC/D,uBAAe,MAAM;AAAA,MACvB;AAAA,IACF,CAAC;AACD,cAAU,iBAAiB,UAAU,CAAC,UAAU;AAC9C,YAAM,SAAS,MAAM;AACrB,UAAI,cAAc,IAAI,OAAO,OAAO,GAAG;AACrC,aAAK,aAAa,MAAM;AAAA,MAC1B;AAAA,IACF,CAAC;AACD,SAAK,UAAU;AAAA,MACb;AAAA,MACA,CAAC,YAAoB,eAA2B,KAAK,uBAAuB,YAAY,UAAU;AAAA,IACpG;AAAA,EACF;AAAA,EAEQ,aAAa,QAA2B;AAC9C,UAAM,UAAU,OAAO,aAAa,MAAM;AAC1C,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AACA,SAAK,QAAQ,SAAU,OAA4B,KAAK;AAAA,EAC1D;AAAA,EAEQ,uBAAuB,YAAoB,YAA8B;AAC/E,SAAK,QAAQ,YAAY,QAAQ,YAAY,UAAU,CAAC;AAAA,EAC1D;AAAA,EAEQ,QAAQ,SAAiB,UAAyB;AACxD,UAAM,QAAQ,KAAK,SAAS,OAAO;AACnC,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AACA,UAAM,QAAiC,CAAC;AACxC,YAAQ,OAAO,SAAS,QAAQ;AAEhC,UAAM,SAAkC,CAAC;AACzC,YAAQ,QAAQ,SAAS,QAAQ,MAAM,YAAY,OAAO,CAAC;AAC3D,SAAK,cAAc,QAAQ,4BAA4B;AAAA,MACrD,OAAO,MAAM;AAAA,MACb,YAAY,MAAM;AAAA,MAClB;AAAA,MACA;AAAA,IACF,CAA8B;AAAA,EAChC;AAAA,EAEQ,WAAW,OAA4B;AAC7C,SAAK,SAAS,iBAA8B,YAAY,EAAE,QAAQ,CAAC,QAAQ;AACzE,UAAI,UAAU,OAAO,oBAAoB,IAAI,aAAa,iBAAiB,MAAM,KAAK;AAAA,IACxF,CAAC;AACD,SAAK,aAAa,iBAA8B,mBAAmB,EAAE,QAAQ,CAAC,YAAY;AACxF,cAAQ,UAAU,OAAO,QAAQ,QAAQ,aAAa,iBAAiB,MAAM,KAAK;AAAA,IACpF,CAAC;AAAA,EACH;AAAA,EAEQ,QAAQ,YAA0C;AACxD,QAAI,KAAK,WAAW,KAAK,aAAa;AACpC,WAAK,QAAQ,gBAAgB;AAC7B,WAAK,YAAY,gBAAgB;AAAA,IACnC;AACA,QAAI,YAAY;AACd,WAAK,aAAa,UAAU;AAAA,IAC9B;AAAA,EACF;AAAA,EAEQ,aAAa,YAA8B;AACjD,QAAI,CAAC,KAAK,WAAW,CAAC,KAAK,aAAa;AACtC;AAAA,IACF;AACA,UAAM,OAAO,KAAK,oBAAoB,QAAQ,UAAU;AACxD,UAAM,eAAgD,CAAC;AACvD,SAAK,WAAW,CAAC;AAEjB,eAAW,OAAO,MAAM;AACtB,YAAM,UAAU,SAAS,kDAAkD,IAAI,EAAE,UAAU;AAC3F,UAAI,gBAAgB;AAEpB,iBAAW,SAAS,IAAI,QAAQ;AAC9B,YAAI,MAAM,QAAQ,WAAW,GAAG;AAC9B;AAAA,QACF;AACA,cAAM,eAAe;AAAA,UACnB,0DAA0D,MAAM,EAAE,0CACxB,MAAM,KAAK;AAAA,QACvD;AACA,mBAAW,SAAS,MAAM,SAAS;AACjC,gBAAM,YAAY,SAAS,QAAQ,MAAM,IAAI,QAAQ;AACrD,uBAAa,YAAY,SAAS;AAClC,eAAK,SAAS,MAAM,EAAE,IAAI,EAAE,OAAO,OAAO,YAAY,UAAU,UAAU;AAAA,QAC5E;AACA,gBAAQ,YAAY,YAAY;AAChC,wBAAgB;AAAA,MAClB;AAEA,UAAI,eAAe;AACjB,aAAK,YAAY,YAAY,OAAO;AACpC,qBAAa,KAAK,EAAE,IAAI,IAAI,IAAI,OAAO,IAAI,MAAM,CAAC;AAAA,MACpD;AAAA,IACF;AAGA,WAAO,OAAO,KAAK,QAAQ,EAAE,QAAQ,CAAC,UAAU,MAAM,MAAM,IAAI,MAAM,YAAY,MAAM,QAAQ,CAAC;AAGjG,QAAI,WAA0B;AAC9B,eAAW,OAAO,cAAc;AAC9B,8BAAa,IAAI;AACjB,WAAK,QAAQ;AAAA,QACX;AAAA,UACE,0CAA0C,IAAI,EAAE,iBAAiB,IAAI,KAAK;AAAA,QAC5E;AAAA,MACF;AAAA,IACF;AACA,SAAK,WAAW,QAAQ;AAAA,EAC1B;AAOF;AA1Oa,iBACK,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAPW,iBAqOK,cACd;AAtOG,IAAM,kBAAN;;;AC1BA,IAAM,wBAAwB;AAAA,EACnC,UAAU,CAAC,iBAAiB;AAAA,EAC5B,iBAAiB,CAAC,QAAQ,eAAe;AAC3C;;;ALKA,IAAM,kBACJ;AAYK,IAAM,UAAN,MAAM,gBAAe,kBAAkB;AAAA,EAsB5C,YAAY,UAAyB,CAAC,GAAG;AACvC,UAAM,OAAO;AALf;AAAA,0BAAiB;AAEjB,SAAiB,aAAa,CAAC,UAA+B,KAAK,eAAe,KAAK;AAMrF,YAAQ,WAAW,iBAAiB,WAAW,KAAK,UAAU;AAAA,EAChE;AAAA,EAEQ,eAAe,OAA4B;AAEjD,UAAM,SAAS,MAAM;AACrB,QAAI,WAAW,OAAO,YAAY,WAAW,OAAO,YAAY,aAAa;AAC3E;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,QAAQ,GAAG;AACnB;AAAA,IACF;AACA,UAAM,MAAM,MAAM,WAAW,MAAM;AACnC,QAAI,CAAC,KAAK;AACR;AAAA,IACF;AACA,UAAM,MAAM,MAAM,IAAI,YAAY;AAClC,QAAI,QAAQ,OAAO,MAAM,UAAU;AACjC,YAAM,eAAe;AACrB,WAAK,KAAK;AAAA,IACZ,WAAW,QAAQ,KAAK;AACtB,YAAM,eAAe;AACrB,WAAK,KAAK;AAAA,IACZ,WAAW,QAAQ,KAAK;AACtB,YAAM,eAAe;AACrB,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AAAA;AAAA,EAGA,UAAgB;AACd,SAAK,QAAQ,WAAW,oBAAoB,WAAW,KAAK,UAAU;AACtE,UAAM,QAAQ;AAAA,EAChB;AAAA;AAAA,EAGA,gBAA+B;AAC7B,WAAO,KAAK,cAAc,KAAK,cAAc;AAAA,EAC/C;AAAA,EAEA,aAAuC;AAGrC,WAAO;AAAA,MACL,GAAG,kBAAkB;AAAA,MACrB,GAAG,QAAO;AAAA,MACV,GAAG,OAAO;AAAA,IACZ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW,aAA+B,CAAC,GAA0B;AACnE,UAAM,MAAqB,EAAE,WAAW,QAAQ,YAAY,CAAC,UAAU,EAAE;AACzE,SAAK,IAAkB,cAAc,EAAE,QAAQ,kBAAkB,GAAG;AACpE,WAAO,IAAI;AAAA,EACb;AAAA;AAAA,EAGA,OAAO,YAAyC;AAC9C,UAAM,UAAU,KAAK,IAAqB,iBAAiB,EAAE,IAAI,WAAW,EAAY;AACxF,QAAI,SAAS;AACX,WAAK,IAAe,WAAW,EAAE,OAAO,SAAS,UAAU;AAAA,IAC7D;AAAA,EACF;AAAA;AAAA,EAGA,iBAAuB;AACrB,SAAK,IAAe,WAAW,EAAE,eAAe;AAAA,EAClD;AAAA;AAAA,EAGA,OAAa;AACX,SAAK,IAAkB,cAAc,EAAE,KAAK;AAAA,EAC9C;AAAA;AAAA,EAGA,OAAa;AACX,SAAK,IAAkB,cAAc,EAAE,KAAK;AAAA,EAC9C;AAAA;AAAA,EAGA,UAAmB;AACjB,WAAO,KAAK,IAAkB,cAAc,EAAE,QAAQ;AAAA,EACxD;AAAA;AAAA,EAGA,UAAmB;AACjB,WAAO,KAAK,IAAkB,cAAc,EAAE,QAAQ;AAAA,EACxD;AACF;AAAA;AAzHa,QAEK,iBAA2C;AAAA,EACzD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AACF;AAfK,IAAM,SAAN;AA2HP,IAAO,gBAAQ;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@d3-polytree/editor",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Polytree editor (create and modify diagrams)",
5
5
  "license": "MIT",
6
6
  "author": "David Castillo",
@@ -23,9 +23,9 @@
23
23
  "sideEffects": false,
24
24
  "dependencies": {
25
25
  "eventemitter3": "^5.0.1",
26
- "@d3-polytree/viewer": "0.1.0",
27
- "@d3-polytree/core": "0.1.0",
28
- "@d3-polytree/interactive-viewer": "0.2.0"
26
+ "@d3-polytree/viewer": "0.1.1",
27
+ "@d3-polytree/core": "0.2.0",
28
+ "@d3-polytree/interactive-viewer": "0.3.0"
29
29
  },
30
30
  "unpkg": "./dist/editor.umd.js",
31
31
  "jsdelivr": "./dist/editor.umd.js",