@pooder/core 0.0.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -20,24 +20,37 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- Circle: () => import_fabric4.Circle,
24
- Ellipse: () => import_fabric4.Ellipse,
25
- Group: () => import_fabric4.Group,
26
- Image: () => import_fabric4.FabricImage,
27
- Line: () => import_fabric4.Line,
28
- Path: () => import_fabric4.Path,
29
- Pattern: () => import_fabric4.Pattern,
30
- Point: () => import_fabric4.Point,
31
- PooderCanvas: () => import_fabric.Canvas,
32
- PooderEditor: () => PooderEditor,
33
- PooderLayer: () => import_fabric2.Group,
34
- PooderObject: () => import_fabric3.FabricObject,
35
- Rect: () => import_fabric4.Rect,
36
- Text: () => import_fabric4.Text,
37
- filters: () => import_fabric4.filters
23
+ CommandService: () => CommandService,
24
+ ConfigurationService: () => ConfigurationService,
25
+ ContributionPointIds: () => ContributionPointIds,
26
+ ContributionRegistry: () => ContributionRegistry,
27
+ ExtensionManager: () => ExtensionManager,
28
+ ExtensionRegistry: () => ExtensionRegistry,
29
+ Pooder: () => Pooder,
30
+ ServiceRegistry: () => ServiceRegistry
38
31
  });
39
32
  module.exports = __toCommonJS(index_exports);
40
33
 
34
+ // src/service.ts
35
+ var ServiceRegistry = class {
36
+ constructor() {
37
+ this.services = /* @__PURE__ */ new Map();
38
+ }
39
+ register(name, service) {
40
+ this.services.set(name, service);
41
+ return service;
42
+ }
43
+ get(serviceName) {
44
+ return this.services.get(serviceName);
45
+ }
46
+ has(serviceName) {
47
+ return this.services.has(serviceName);
48
+ }
49
+ delete(serviceName) {
50
+ this.services.delete(serviceName);
51
+ }
52
+ };
53
+
41
54
  // src/event.ts
42
55
  var EventBus = class {
43
56
  constructor() {
@@ -74,364 +87,500 @@ var EventBus = class {
74
87
  return (_b = (_a = this.events.get(event)) == null ? void 0 : _a.length) != null ? _b : 0;
75
88
  }
76
89
  };
90
+ var event_default = EventBus;
77
91
 
78
- // src/command.ts
79
- var DefaultCommandManager = class {
80
- constructor(editor) {
81
- this.editor = editor;
82
- }
83
- register(name, command) {
84
- if (this.editor.commands.has(name)) {
85
- console.warn(`Command "${name}" already exists. It will be overwritten.`);
86
- }
87
- this.editor.commands.set(name, command);
88
- }
89
- unregister(name) {
90
- this.editor.commands.delete(name);
92
+ // src/contribution/points.ts
93
+ var ContributionPointIds = {
94
+ CONTRIBUTIONS: "contribution.point.contributions",
95
+ COMMANDS: "contribution.point.commands",
96
+ TOOLS: "contribution.point.tools",
97
+ VIEWS: "contribution.point.views",
98
+ CONFIGURATIONS: "contribution.point.configurations"
99
+ };
100
+
101
+ // src/contribution/registry.ts
102
+ var ContributionRegistry = class {
103
+ constructor() {
104
+ this.points = /* @__PURE__ */ new Map();
105
+ this.contributions = {
106
+ byId: /* @__PURE__ */ new Map(),
107
+ byPointId: /* @__PURE__ */ new Map()
108
+ };
91
109
  }
92
- execute(name, ...args) {
93
- const command = this.editor.commands.get(name);
94
- if (!command) {
95
- console.warn(`Command "${name}" not found`);
96
- return false;
110
+ /**
111
+ * Register a new contribution point
112
+ */
113
+ registerPoint(point) {
114
+ if (this.points.has(point.id)) {
115
+ console.warn(
116
+ `Contribution point ${point.id} already exists. Overwriting definitions may cause issues.`
117
+ );
97
118
  }
98
- try {
99
- return command.execute(...args);
100
- } catch (e) {
101
- console.error(`Error executing command "${name}":`, e);
102
- return false;
119
+ this.points.set(point.id, point);
120
+ if (!this.contributions.byPointId.has(point.id)) {
121
+ this.contributions.byPointId.set(point.id, []);
103
122
  }
104
123
  }
105
- get(name) {
106
- return this.editor.commands.get(name);
107
- }
108
- has(name) {
109
- return this.editor.commands.has(name);
110
- }
111
- count() {
112
- return this.editor.commands.size;
113
- }
114
- list() {
115
- return Array.from(this.editor.commands.keys());
124
+ /**
125
+ * Register a contribution to a specific point
126
+ * @returns Disposable to unregister the contribution
127
+ */
128
+ register(pointId, contribution) {
129
+ if (this.contributions.byId.has(contribution.id)) {
130
+ console.warn(
131
+ `Contribution with ID "${contribution.id}" is already registered. Overwriting.`
132
+ );
133
+ this.unregister(pointId, contribution.id);
134
+ }
135
+ if (!this.points.has(pointId)) {
136
+ console.warn(
137
+ `Contribution point ${pointId} does not exist. The contribution ${contribution.id} will be queued but may not be valid.`
138
+ );
139
+ if (!this.contributions.byPointId.has(pointId)) {
140
+ this.contributions.byPointId.set(pointId, []);
141
+ }
142
+ }
143
+ const point = this.points.get(pointId);
144
+ if (point == null ? void 0 : point.validate) {
145
+ try {
146
+ if (!point.validate(contribution.data)) {
147
+ console.error(
148
+ `Contribution ${contribution.id} failed validation for point ${pointId}.`
149
+ );
150
+ return { dispose: () => {
151
+ } };
152
+ }
153
+ } catch (e) {
154
+ console.error(
155
+ `Validation error for contribution ${contribution.id}:`,
156
+ e
157
+ );
158
+ return { dispose: () => {
159
+ } };
160
+ }
161
+ }
162
+ const arr = this.contributions.byPointId.get(pointId);
163
+ arr.push(contribution);
164
+ this.contributions.byId.set(contribution.id, contribution);
165
+ if (pointId === ContributionPointIds.CONTRIBUTIONS) {
166
+ this.registerPoint(contribution.data);
167
+ }
168
+ return {
169
+ dispose: () => {
170
+ this.unregister(pointId, contribution.id);
171
+ }
172
+ };
116
173
  }
117
- clear() {
118
- this.editor.commands.clear();
174
+ /**
175
+ * Get all contributions for a given point
176
+ */
177
+ get(pointId) {
178
+ var _a;
179
+ return Array.from(
180
+ ((_a = this.contributions.byPointId.get(pointId)) == null ? void 0 : _a.values()) || []
181
+ );
182
+ }
183
+ /**
184
+ * Get a specific contribution by ID
185
+ */
186
+ getById(id) {
187
+ return this.contributions.byId.get(id);
188
+ }
189
+ /**
190
+ * Get the contribution point definition
191
+ */
192
+ getPoint(pointId) {
193
+ return this.points.get(pointId);
194
+ }
195
+ /**
196
+ * Unregister a contribution
197
+ */
198
+ unregister(pointId, contributionId) {
199
+ const arr = this.contributions.byPointId.get(pointId);
200
+ arr == null ? void 0 : arr.splice(
201
+ arr.findIndex((c) => c.id === contributionId),
202
+ 1
203
+ );
204
+ this.contributions.byId.delete(contributionId);
119
205
  }
120
206
  };
121
207
 
122
208
  // src/extension.ts
123
- var DefaultExtensionManager = class {
124
- constructor(editor) {
125
- this.mounted = false;
126
- this.editor = editor;
127
- }
128
- _registerCommands(extension) {
129
- if (extension.commands) {
130
- Object.entries(extension.commands).forEach(([name, command]) => {
131
- const commandName = `${extension.name}.${name}`;
132
- this.editor.registerCommand(commandName, command);
133
- });
134
- }
135
- }
136
- _unregisterCommands(extension) {
137
- if (extension.commands) {
138
- Object.keys(extension.commands).forEach((name) => {
139
- const commandName = `${extension.name}.${name}`;
140
- this.editor.unregisterCommand(commandName);
141
- });
142
- }
209
+ var ExtensionRegistry = class extends Map {
210
+ };
211
+ var ExtensionManager = class {
212
+ constructor(context) {
213
+ this.extensionRegistry = new ExtensionRegistry();
214
+ this.extensionDisposables = /* @__PURE__ */ new Map();
215
+ this.context = context;
143
216
  }
144
217
  register(extension) {
145
- var _a, _b;
146
- if (this.editor.extensions.has(extension.name)) {
147
- console.warn(`Plugin "${extension.name}" already registered. It will be overwritten.`);
218
+ if (this.extensionRegistry.has(extension.id)) {
219
+ console.warn(
220
+ `Plugin "${extension.id}" already registered. It will be overwritten.`
221
+ );
148
222
  }
149
- try {
150
- if (extension.enabled === void 0) {
151
- extension.enabled = true;
223
+ this.extensionDisposables.set(extension.id, []);
224
+ const disposables = this.extensionDisposables.get(extension.id);
225
+ if (extension.contribute) {
226
+ for (const [pointId, items] of Object.entries(extension.contribute())) {
227
+ if (Array.isArray(items)) {
228
+ items.forEach((item, index) => {
229
+ const contributionId = item.id || (item.command ? item.command : `${extension.id}.${pointId}.${index}`);
230
+ const contribution = {
231
+ id: contributionId,
232
+ metadata: {
233
+ extensionId: extension.id,
234
+ ...item == null ? void 0 : item.metadata
235
+ },
236
+ data: item
237
+ };
238
+ const disposable = this.context.contributions.register(
239
+ pointId,
240
+ contribution
241
+ );
242
+ disposables.push(disposable);
243
+ const dispose = this.collectContribution(pointId, contribution);
244
+ if (dispose) {
245
+ disposables.push(dispose);
246
+ }
247
+ });
248
+ }
152
249
  }
153
- this.editor.extensions.set(extension.name, extension);
154
- (_a = extension.onCreate) == null ? void 0 : _a.call(extension, this.editor);
250
+ }
251
+ try {
252
+ this.extensionRegistry.set(extension.id, extension);
253
+ this.context.eventBus.emit("extension:register", extension);
155
254
  } catch (error) {
156
- console.error(`Error in onCreate hook for plugin "${extension.name}":`, error);
255
+ console.error(
256
+ `Error in onCreate hook for plugin "${extension.id}":`,
257
+ error
258
+ );
157
259
  }
158
- if (extension.enabled) {
159
- this._registerCommands(extension);
160
- if (this.mounted) {
161
- try {
162
- (_b = extension.onMount) == null ? void 0 : _b.call(extension, this.editor);
163
- } catch (error) {
164
- console.error(`Error in onMount hook for plugin "${extension.name}":`, error);
165
- }
166
- }
260
+ try {
261
+ extension.activate(this.context);
262
+ } catch (error) {
263
+ console.error(
264
+ `Error in onActivate hook for plugin "${extension.id}":`,
265
+ error
266
+ );
267
+ }
268
+ console.log(`Plugin "${extension.id}" registered successfully`);
269
+ }
270
+ collectContribution(pointId, item) {
271
+ if (pointId === ContributionPointIds.CONFIGURATIONS) {
272
+ const configService = this.context.services.get(
273
+ "ConfigurationService"
274
+ );
275
+ configService == null ? void 0 : configService.initializeDefaults([item.data]);
276
+ }
277
+ if (pointId === ContributionPointIds.COMMANDS && item.data.handler) {
278
+ const commandService = this.context.services.get("CommandService");
279
+ return commandService.registerCommand(item.id, item.data.handler);
167
280
  }
168
- console.log(`Plugin "${extension.name}" registered successfully`);
169
281
  }
170
282
  unregister(name) {
171
- var _a, _b;
172
- const extension = this.editor.extensions.get(name);
283
+ const extension = this.extensionRegistry.get(name);
173
284
  if (!extension) {
174
285
  console.warn(`Plugin "${name}" not found.`);
175
286
  return;
176
287
  }
177
- if (this.mounted && extension.enabled) {
178
- try {
179
- (_a = extension.onUnmount) == null ? void 0 : _a.call(extension, this.editor);
180
- } catch (error) {
181
- console.error(`Error in onUnmount hook for plugin "${name}":`, error);
182
- }
183
- }
184
288
  try {
185
- (_b = extension.onDestroy) == null ? void 0 : _b.call(extension, this.editor);
289
+ extension.deactivate(this.context);
186
290
  } catch (error) {
187
- console.error(`Error in onDestroy hook for plugin "${name}":`, error);
291
+ console.error(`Error in deactivate for plugin "${name}":`, error);
292
+ }
293
+ const disposables = this.extensionDisposables.get(name);
294
+ if (disposables) {
295
+ disposables.forEach((d) => d.dispose());
296
+ this.extensionDisposables.delete(name);
188
297
  }
189
- this._unregisterCommands(extension);
190
- this.editor.extensions.delete(name);
298
+ this.extensionRegistry.delete(name);
191
299
  console.log(`Plugin "${name}" unregistered`);
192
300
  return true;
193
301
  }
194
302
  enable(name) {
195
- var _a;
196
- const extension = this.get(name);
303
+ const extension = this.extensionRegistry.get(name);
197
304
  if (!extension) {
198
305
  console.warn(`Plugin "${name}" not found.`);
199
306
  return;
200
307
  }
201
- if (extension.enabled) return;
202
- extension.enabled = true;
203
- this._registerCommands(extension);
204
- if (this.mounted) {
205
- try {
206
- (_a = extension.onMount) == null ? void 0 : _a.call(extension, this.editor);
207
- } catch (error) {
208
- console.error(`Error in onMount hook for plugin "${name}":`, error);
209
- }
210
- }
211
308
  }
212
309
  disable(name) {
213
- var _a;
214
- const extension = this.get(name);
310
+ const extension = this.extensionRegistry.get(name);
215
311
  if (!extension) {
216
312
  console.warn(`Plugin "${name}" not found.`);
217
313
  return;
218
314
  }
219
- if (!extension.enabled) return;
220
- extension.enabled = false;
221
- this._unregisterCommands(extension);
222
- if (this.mounted) {
223
- try {
224
- (_a = extension.onUnmount) == null ? void 0 : _a.call(extension, this.editor);
225
- } catch (error) {
226
- console.error(`Error in onUnmount hook for plugin "${name}":`, error);
227
- }
228
- }
229
- }
230
- get(name) {
231
- return this.editor.extensions.get(name);
232
- }
233
- has(name) {
234
- return this.editor.extensions.has(name);
235
- }
236
- count() {
237
- return this.editor.extensions.size;
238
- }
239
- list() {
240
- return Array.from(this.editor.extensions.values());
241
- }
242
- mount() {
243
- if (this.mounted) return;
244
- this.editor.extensions.forEach((extension) => {
245
- var _a;
246
- if (extension.enabled) {
247
- try {
248
- (_a = extension.onMount) == null ? void 0 : _a.call(extension, this.editor);
249
- } catch (e) {
250
- console.error(`Error in onMount hook for plugin "${extension.name}":`, e);
251
- }
252
- }
253
- });
254
- this.mounted = true;
255
315
  }
256
316
  update() {
257
- const state = this.editor.getState();
258
- this.editor.extensions.forEach((extension) => {
259
- var _a;
260
- if (extension.enabled) {
261
- try {
262
- (_a = extension.onUpdate) == null ? void 0 : _a.call(extension, this.editor, state);
263
- } catch (e) {
264
- console.error(`Error in onUpdate hook for plugin "${extension.name}":`, e);
265
- }
266
- }
267
- });
268
317
  }
269
318
  destroy() {
270
- const extensionNames = Array.from(this.editor.extensions.keys());
319
+ const extensionNames = Array.from(this.extensionRegistry.keys());
271
320
  extensionNames.forEach((name) => this.unregister(name));
272
- this.mounted = false;
273
321
  }
274
322
  };
275
323
 
276
- // src/canvas.ts
277
- var import_fabric = require("fabric");
278
-
279
- // src/editor.ts
280
- var PooderEditor = class {
281
- constructor(el, options = {}) {
282
- this.extensions = /* @__PURE__ */ new Map();
324
+ // src/services/CommandService.ts
325
+ var CommandService = class {
326
+ constructor() {
283
327
  this.commands = /* @__PURE__ */ new Map();
284
- this.destroyed = false;
285
- this.state = {
286
- width: options.width || 800,
287
- height: options.height || 600
288
- };
289
- this.canvas = new import_fabric.Canvas(el, { width: this.state.width, height: this.state.height });
290
- this.eventBus = new EventBus();
291
- this.commandManager = new DefaultCommandManager(this);
292
- this.extensionManager = new DefaultExtensionManager(this);
293
- if (options.extensions && options.extensions.length > 0) {
294
- options.extensions.forEach(this.extensionManager.register);
295
- }
296
- this.extensionManager.mount();
297
- console.log("Editor initialized with", this.extensionManager.count(), "plugins");
298
328
  }
299
- use(extension) {
300
- if (this.destroyed) {
301
- throw new Error("Cannot register plugin: Editor is destroyed");
329
+ /**
330
+ * Register a command
331
+ * @param commandId Command Name (ID)
332
+ * @param handler Command handler function
333
+ * @param thisArg The `this` context for the handler
334
+ * @returns Disposable to unregister the command
335
+ */
336
+ registerCommand(commandId, handler, thisArg) {
337
+ if (this.commands.has(commandId)) {
338
+ console.warn(
339
+ `Command "${commandId}" is already registered. Overwriting.`
340
+ );
302
341
  }
303
- this.extensionManager.register(extension);
304
- this.emit("update", this.state);
342
+ const command = {
343
+ id: commandId,
344
+ handler: thisArg ? handler.bind(thisArg) : handler
345
+ };
346
+ this.commands.set(commandId, command);
347
+ return {
348
+ dispose: () => {
349
+ if (this.commands.get(commandId) === command) {
350
+ this.commands.delete(commandId);
351
+ }
352
+ }
353
+ };
305
354
  }
306
- unuse(name) {
307
- return this.extensionManager.unregister(name);
355
+ /**
356
+ * Execute a command
357
+ * @param commandId Command Name (ID)
358
+ * @param args Arguments to pass to the handler
359
+ * @returns The result of the command handler
360
+ */
361
+ async executeCommand(commandId, ...args) {
362
+ const command = this.commands.get(commandId);
363
+ if (!command) {
364
+ throw new Error(`Command "${commandId}" not found.`);
365
+ }
366
+ try {
367
+ return await command.handler(...args);
368
+ } catch (error) {
369
+ console.error(`Error executing command "${commandId}":`, error);
370
+ throw error;
371
+ }
308
372
  }
309
- getExtension(name) {
310
- return this.extensionManager.get(name);
373
+ /**
374
+ * Get all registered commands
375
+ */
376
+ getCommands() {
377
+ return this.commands;
311
378
  }
312
- getExtensions() {
313
- return this.extensionManager.list();
379
+ /**
380
+ * Get a specific command
381
+ */
382
+ getCommand(commandId) {
383
+ return this.commands.get(commandId);
314
384
  }
315
- enableExtension(name) {
316
- this.extensionManager.enable(name);
317
- this.emit("update", this.state);
385
+ dispose() {
386
+ this.commands.clear();
318
387
  }
319
- disableExtension(name) {
320
- this.extensionManager.disable(name);
321
- this.emit("update", this.state);
388
+ };
389
+
390
+ // src/services/ConfigurationService.ts
391
+ var ConfigurationService = class {
392
+ constructor() {
393
+ this.configValues = /* @__PURE__ */ new Map();
394
+ this.eventBus = new event_default();
395
+ }
396
+ /**
397
+ * Get a configuration value.
398
+ */
399
+ get(key, defaultValue) {
400
+ if (this.configValues.has(key)) {
401
+ return this.configValues.get(key);
402
+ }
403
+ return defaultValue;
404
+ }
405
+ /**
406
+ * Update a configuration value.
407
+ * Emits 'change' event.
408
+ */
409
+ update(key, value) {
410
+ const oldValue = this.configValues.get(key);
411
+ if (oldValue !== value) {
412
+ this.configValues.set(key, value);
413
+ this.eventBus.emit(`change:${key}`, { key, value, oldValue });
414
+ this.eventBus.emit("change", { key, value, oldValue });
415
+ }
322
416
  }
323
- registerCommand(name, command) {
324
- this.commandManager.register(name, command);
417
+ /**
418
+ * Listen for changes to a specific configuration key.
419
+ */
420
+ onDidChange(key, callback) {
421
+ this.eventBus.on(`change:${key}`, callback);
422
+ return {
423
+ dispose: () => this.eventBus.off(`change:${key}`, callback)
424
+ };
325
425
  }
326
- unregisterCommand(name) {
327
- this.commandManager.unregister(name);
426
+ /**
427
+ * Listen for any configuration change.
428
+ */
429
+ onAnyChange(callback) {
430
+ this.eventBus.on("change", callback);
431
+ return {
432
+ dispose: () => this.eventBus.off("change", callback)
433
+ };
328
434
  }
329
- executeCommand(name, ...args) {
330
- if (this.destroyed) {
331
- console.warn("Cannot execute command: Editor is destroyed");
332
- return false;
435
+ /**
436
+ * Export current configuration state as a JSON-serializable object.
437
+ * Useful for saving configuration templates.
438
+ */
439
+ export() {
440
+ const exportData = {};
441
+ for (const [key, value] of this.configValues) {
442
+ exportData[key] = value;
443
+ }
444
+ return exportData;
445
+ }
446
+ /**
447
+ * Import configuration from a JSON object.
448
+ * This will merge the provided configuration with the current state,
449
+ * overwriting existing keys and triggering change events.
450
+ */
451
+ import(data) {
452
+ if (!data || typeof data !== "object") {
453
+ console.warn("ConfigurationService: Import data must be an object.");
454
+ return;
333
455
  }
334
- this.emit("beforeCommand", name, ...args);
335
- const result = this.commandManager.execute(name, ...args);
336
- this.emit("afterCommand", name, args, result);
337
- return result;
456
+ Object.entries(data).forEach(([key, value]) => {
457
+ this.update(key, value);
458
+ });
338
459
  }
339
- on(event, handler, priority) {
340
- this.eventBus.on(event, handler, priority);
460
+ /**
461
+ * Initialize configuration with defaults from contributions.
462
+ * This should be called when a contribution is registered.
463
+ */
464
+ initializeDefaults(contributions) {
465
+ contributions.forEach((contrib) => {
466
+ if (!contrib.id) {
467
+ console.warn(
468
+ "Configuration contribution missing 'id'. Skipping default initialization.",
469
+ contrib
470
+ );
471
+ return;
472
+ }
473
+ if (!this.configValues.has(contrib.id) && contrib.default !== void 0) {
474
+ this.configValues.set(contrib.id, contrib.default);
475
+ }
476
+ });
341
477
  }
342
- off(event, handler) {
343
- this.eventBus.off(event, handler);
478
+ dispose() {
479
+ this.configValues.clear();
344
480
  }
345
- emit(event, ...args) {
346
- this.eventBus.emit(event, ...args);
481
+ };
482
+
483
+ // src/index.ts
484
+ var Pooder = class {
485
+ constructor() {
486
+ this.eventBus = new event_default();
487
+ this.services = new ServiceRegistry();
488
+ this.contributions = new ContributionRegistry();
489
+ this.initDefaultContributionPoints();
490
+ const commandService = new CommandService();
491
+ this.registerService(commandService);
492
+ const configurationService = new ConfigurationService();
493
+ this.registerService(configurationService);
494
+ const context = {
495
+ eventBus: this.eventBus,
496
+ services: {
497
+ get: (serviceName) => this.services.get(serviceName)
498
+ },
499
+ contributions: {
500
+ get: (pointId) => this.getContributions(pointId),
501
+ register: (pointId, contribution) => this.registerContribution(pointId, contribution)
502
+ }
503
+ };
504
+ this.extensionManager = new ExtensionManager(context);
347
505
  }
348
- getObjects() {
349
- if (this.destroyed) {
350
- throw new Error("Cannot get objects: Editor is destroyed");
351
- }
352
- return this.canvas.getObjects();
506
+ initDefaultContributionPoints() {
507
+ this.registerContributionPoint({
508
+ id: ContributionPointIds.CONTRIBUTIONS,
509
+ description: "Contribution point for contribution points"
510
+ });
511
+ this.registerContributionPoint({
512
+ id: ContributionPointIds.COMMANDS,
513
+ description: "Contribution point for commands"
514
+ });
515
+ this.registerContributionPoint({
516
+ id: ContributionPointIds.TOOLS,
517
+ description: "Contribution point for tools"
518
+ });
519
+ this.registerContributionPoint({
520
+ id: ContributionPointIds.VIEWS,
521
+ description: "Contribution point for UI views"
522
+ });
523
+ this.registerContributionPoint({
524
+ id: ContributionPointIds.CONFIGURATIONS,
525
+ description: "Contribution point for configurations"
526
+ });
353
527
  }
354
- getObject(id, layerId) {
528
+ // --- Service Management ---
529
+ registerService(service) {
355
530
  var _a;
356
- let objs;
357
- if (layerId) {
358
- objs = (_a = this.getLayer(layerId)) == null ? void 0 : _a.getObjects();
359
- } else {
360
- objs = this.getObjects();
531
+ const serviceId = service.constructor.name;
532
+ try {
533
+ (_a = service == null ? void 0 : service.init) == null ? void 0 : _a.call(service);
534
+ } catch (e) {
535
+ console.error(`Error initializing service ${serviceId}:`, e);
536
+ return false;
361
537
  }
362
- return objs == null ? void 0 : objs.find((obj) => {
363
- var _a2;
364
- return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.id) === id;
365
- });
366
- }
367
- getLayers() {
368
- return this.getObjects().filter((obj) => obj.type === "group");
369
- }
370
- getLayer(id) {
371
- return this.getLayers().find((obj) => {
372
- var _a;
373
- return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.id) === id;
374
- });
538
+ this.services.register(serviceId, service);
539
+ this.eventBus.emit("service:register", service);
540
+ return true;
375
541
  }
376
- updateState(updater) {
377
- if (this.destroyed) {
378
- console.warn("Cannot update state: Editor is destroyed");
379
- return;
542
+ unregisterService(service) {
543
+ var _a;
544
+ const serviceId = service.constructor.name;
545
+ if (!this.services.has(serviceId)) {
546
+ console.warn(`Service ${serviceId} is not registered.`);
547
+ return true;
548
+ }
549
+ try {
550
+ (_a = service == null ? void 0 : service.dispose) == null ? void 0 : _a.call(service);
551
+ } catch (e) {
552
+ console.error(`Error disposing service ${serviceId}:`, e);
553
+ return false;
380
554
  }
381
- this.state = updater(this.state);
382
- this.extensionManager.update();
383
- this.emit("update", this.state);
555
+ this.services.delete(serviceId);
556
+ this.eventBus.emit("service:unregister", service);
557
+ return true;
384
558
  }
385
- toJSON() {
386
- return {
387
- width: this.state.width,
388
- height: this.state.height,
389
- metadata: this.state.metadata
390
- };
559
+ getService(id) {
560
+ return this.services.get(id);
391
561
  }
392
- async loadFromJSON(json) {
562
+ // --- Contribution Management ---
563
+ registerContributionPoint(point) {
564
+ this.contributions.registerPoint(point);
565
+ this.eventBus.emit("contribution:point:register", point);
393
566
  }
394
- getState() {
395
- return { ...this.state };
567
+ registerContribution(pointId, contribution) {
568
+ const disposable = this.contributions.register(pointId, contribution);
569
+ this.eventBus.emit("contribution:register", { ...contribution, pointId });
570
+ return disposable;
396
571
  }
397
- destroy() {
398
- if (this.destroyed) return;
399
- this.emit("beforeDestroy");
400
- this.canvas.dispose();
401
- this.extensionManager.destroy();
402
- this.eventBus.clear();
403
- this.commandManager.clear();
404
- this.destroyed = true;
405
- console.log("Editor destroyed");
406
- }
407
- isDestroyed() {
408
- return this.destroyed;
572
+ getContributions(pointId) {
573
+ return this.contributions.get(pointId);
409
574
  }
410
575
  };
411
-
412
- // src/layer.ts
413
- var import_fabric2 = require("fabric");
414
-
415
- // src/obj.ts
416
- var import_fabric3 = require("fabric");
417
-
418
- // src/index.ts
419
- var import_fabric4 = require("fabric");
420
576
  // Annotate the CommonJS export names for ESM import in node:
421
577
  0 && (module.exports = {
422
- Circle,
423
- Ellipse,
424
- Group,
425
- Image,
426
- Line,
427
- Path,
428
- Pattern,
429
- Point,
430
- PooderCanvas,
431
- PooderEditor,
432
- PooderLayer,
433
- PooderObject,
434
- Rect,
435
- Text,
436
- filters
578
+ CommandService,
579
+ ConfigurationService,
580
+ ContributionPointIds,
581
+ ContributionRegistry,
582
+ ExtensionManager,
583
+ ExtensionRegistry,
584
+ Pooder,
585
+ ServiceRegistry
437
586
  });