@cocreate/events 1.34.0 → 2.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/src/index.js CHANGED
@@ -18,17 +18,58 @@
18
18
  // Commercial Licensing Information:
19
19
  // For commercial use of this software without the copyleft provisions of the AGPLv3,
20
20
  // you must obtain a commercial license from CoCreate LLC.
21
- // For details, visit <https://cocreate.app/licenses/> or contact us at sales@cocreate.app.
21
+ // For details, visit <https://CoCreateJS.com/licenses/> or contact us at sales@CoCreateJS.com.
22
22
 
23
- import { queryElements } from "@cocreate/utils";
23
+ import { queryElements, resolveProperty, astAsync } from "@cocreate/utils";
24
24
  import action from "@cocreate/actions";
25
25
  import observer from "@cocreate/observer";
26
26
  import "@cocreate/element-prototype";
27
27
  import { getAttribute } from "@cocreate/element-prototype/src/getAttribute.js";
28
28
 
29
+ function resolvePropertyPath(object, path) {
30
+ const segments = path.split(".");
31
+ let target = object;
32
+
33
+ for (let index = 0; index < segments.length; index++) {
34
+ if (target == null) return null;
35
+ const key = resolveProperty(target, segments[index]) || segments[index];
36
+ if (index === segments.length - 1)
37
+ return { target, key, value: target[key] };
38
+ target = target[key];
39
+ }
40
+
41
+ return null;
42
+ }
43
+
29
44
  const CoCreateEvents = {
30
45
  elements: new Map(),
31
46
 
47
+ // Known targets initialize for every prefix without an additional marker.
48
+ // Arbitrary prefix.* properties and methods still opt in through
49
+ // [prefix], [prefix-group], or [prefix-query].
50
+ knownTargets: [
51
+ "class",
52
+ "src",
53
+ "href",
54
+ "value",
55
+ "hidden",
56
+ "disabled",
57
+ "checked",
58
+ "selected",
59
+ "aria-expanded",
60
+ "aria-hidden",
61
+ "aria-pressed",
62
+ "aria-current",
63
+ "textContent",
64
+ "innerHTML",
65
+ "save"
66
+ ],
67
+
68
+ /**
69
+ *
70
+ * @public
71
+ * @environment client
72
+ */
32
73
  init: function (prefix, events) {
33
74
  if (prefix && events) {
34
75
  this.initPrefix(prefix, events);
@@ -48,7 +89,8 @@ const CoCreateEvents = {
48
89
  "resize": ["onload", "resize"],
49
90
  "localstorage": ["onload"],
50
91
  "focus": ["focus"],
51
- "blur": ["blur"]
92
+ "blur": ["blur"],
93
+ "error": ["error"]
52
94
  };
53
95
 
54
96
  for (const [p, e] of Object.entries(defaults)) {
@@ -59,11 +101,11 @@ const CoCreateEvents = {
59
101
  // Initialize from existing elements with [event-name]
60
102
  const customEventEls = document.querySelectorAll("[event-name]");
61
103
  const processedNames = new Set();
62
-
104
+
63
105
  for (const customEventEl of customEventEls) {
64
106
  let names = customEventEl.getAttribute("event-name");
65
107
  if (!names) continue;
66
-
108
+
67
109
  names.split(",").forEach(name => {
68
110
  name = name.trim();
69
111
  if (name && !processedNames.has(name)) {
@@ -89,6 +131,11 @@ const CoCreateEvents = {
89
131
  });
90
132
  },
91
133
 
134
+ /**
135
+ *
136
+ * @public
137
+ * @environment client
138
+ */
92
139
  initPrefix: function (prefix, events) {
93
140
  action.init({
94
141
  name: prefix,
@@ -105,7 +152,14 @@ const CoCreateEvents = {
105
152
  });
106
153
 
107
154
  // Updated selector to use dash for options: prefix-group, prefix-query
108
- const selector = `[${prefix}], [${prefix}-group], [${prefix}-query]`;
155
+ const knownTargets = this.knownTargets.map(target => `[${prefix}\\.${target}]`);
156
+ const selector = [
157
+ `[${prefix}]`,
158
+ `[${prefix}-group]`,
159
+ `[${prefix}-query]`,
160
+ `[${prefix}-element]`,
161
+ ...knownTargets
162
+ ].join(", ");
109
163
 
110
164
  observer.init({
111
165
  name: "CoCreateEventAttributes",
@@ -122,10 +176,20 @@ const CoCreateEvents = {
122
176
  }
123
177
  });
124
178
 
179
+ /**
180
+ *
181
+ * @public
182
+ * @environment client
183
+ */
125
184
  const elements = document.querySelectorAll(selector);
126
185
  this.initElements(elements, prefix, events);
127
186
  },
128
187
 
188
+ /**
189
+ *
190
+ * @public
191
+ * @environment client
192
+ */
129
193
  initElements: function (elements, prefix, events = []) {
130
194
  for (const el of elements) {
131
195
  let isEventable = true;
@@ -206,14 +270,29 @@ const CoCreateEvents = {
206
270
 
207
271
  const prefixData = elData[prefix];
208
272
 
273
+ // A new checked state must propagate even after an earlier
274
+ // input/change event; CRUD updates use the same event path.
275
+ const selectionChanged =
276
+ (target.type === "checkbox" || target.type === "radio") &&
277
+ prefixData.checked !== target.checked;
278
+ if (
279
+ event.detail?.skip === true && prefixData.prev === event.type &&
280
+ ["input", "change"].includes(event.type) && !selectionChanged
281
+ ) {
282
+ prefixData.prev = "";
283
+ return
284
+ }
285
+
209
286
  // Debounce/Prevent duplicate mouse events if needed
210
287
  if (prefixData.prev === event.type && ["mouseover", "mouseout"].includes(event.type)) {
211
288
  return;
212
289
  }
213
290
  prefixData.prev = event.type;
291
+ if (target.type === "checkbox" || target.type === "radio")
292
+ prefixData.checked = target.checked;
214
293
 
215
294
  // Check for 'actions' blocking
216
- const actionsAttr = target.getAttribute("actions") || "";
295
+ const actionsAttr = target.attributes.getNamedItem("actions")?.value || "";
217
296
  if (actionsAttr.includes(prefix)) return;
218
297
 
219
298
  // Handle lifecycle controls (using dash)
@@ -222,7 +301,7 @@ const CoCreateEvents = {
222
301
  { attr: "stop-propagation", method: "stopPropagation" },
223
302
  { attr: "stop-immediate-propagation", method: "stopImmediatePropagation" }
224
303
  ];
225
-
304
+
226
305
  for (const { attr, method } of lifecycleAttributes) {
227
306
  const attrValue = target.getAttribute(`${prefix}-${attr}`);
228
307
  if (attrValue !== null && attrValue !== "false") {
@@ -234,13 +313,18 @@ const CoCreateEvents = {
234
313
  }
235
314
  },
236
315
 
316
+ /**
317
+ *
318
+ * @public
319
+ * @environment client
320
+ */
237
321
  _initObserver: function (el, prefix) {
238
322
  // Updated to dash: prefix-selector, prefix-query, prefix-attribute-filter, prefix-types
239
323
  let selector = el.getAttribute(`${prefix}-selector`) || el.getAttribute(`${prefix}-query`) || "";
240
324
  let attributeFilter = (el.getAttribute(`${prefix}-attribute-filter`) || "")
241
325
  .split(/\s*,\s*/)
242
326
  .filter(item => item);
243
-
327
+
244
328
  let types = (el.getAttribute(`${prefix}-types`) || "")
245
329
  .split(/\s*,\s*/)
246
330
  .filter(item => item);
@@ -269,17 +353,29 @@ const CoCreateEvents = {
269
353
  }
270
354
  },
271
355
 
356
+ /**
357
+ *
358
+ * @public
359
+ * @environment client
360
+ */
272
361
  _initResizeObserver: function (el, prefix) {
273
362
  const resizeObserver = new ResizeObserver((entries) => {
274
363
  const lastEntry = entries[entries.length - 1];
275
364
  const { width } = lastEntry.contentRect;
276
- // Keeps dash style for this status attribute
277
- el.setAttribute(`${prefix}-if-value`, width + "px");
365
+ const widthValue = width + "px";
366
+ el.width = widthValue;
367
+ // Keeps dash style for conditional resize bindings.
368
+ el.setAttribute(`${prefix}-if-value`, widthValue);
278
369
  this.__updateElements(el, prefix);
279
370
  });
280
371
  resizeObserver.observe(el);
281
372
  },
282
373
 
374
+ /**
375
+ *
376
+ * @public
377
+ * @environment client
378
+ */
283
379
  _initIntersectionObserver: function (el, prefix) {
284
380
  // Updated to dash
285
381
  const rootSelector = el.getAttribute(`${prefix}-root`);
@@ -289,8 +385,8 @@ const CoCreateEvents = {
289
385
  const trigger = el.getAttribute(`${prefix}-trigger`) || "both";
290
386
 
291
387
  const root = rootSelector ? document.querySelector(rootSelector) : null;
292
- const validThreshold = Array.isArray(threshold)
293
- ? threshold.filter(v => v >= 0 && v <= 1)
388
+ const validThreshold = Array.isArray(threshold)
389
+ ? threshold.filter(v => v >= 0 && v <= 1)
294
390
  : [0];
295
391
 
296
392
  const once = el.getAttribute(`${prefix}-once`);
@@ -321,20 +417,25 @@ const CoCreateEvents = {
321
417
  intersectionObserver.observe(el);
322
418
  },
323
419
 
420
+ /**
421
+ *
422
+ * @public
423
+ * @environment client
424
+ */
324
425
  __updateElements: async function (rootElement, prefix, events, params) {
325
426
  if (!rootElement.isConnected) return;
326
427
 
327
428
  // 1. Determine targets based on prefix-group
328
429
  let sourceElements = [rootElement];
329
430
  const sourceGroup = rootElement.getAttribute(`${prefix}-group`);
330
-
431
+
331
432
  if (sourceGroup) {
332
433
  sourceElements = document.querySelectorAll(`[${prefix}-group="${sourceGroup}"]`);
333
434
  }
334
435
 
335
436
  // 2. Iterate through sourceElements
336
437
  for (const sourceElement of sourceElements) {
337
-
438
+
338
439
  // --- Global Options (Dash) ---
339
440
 
340
441
  // onEvent
@@ -353,18 +454,18 @@ const CoCreateEvents = {
353
454
  const intervalAttr = sourceElement.getAttribute(`${prefix}-set-interval`);
354
455
  if (intervalAttr !== null) {
355
456
  const intervalMs = parseInt(intervalAttr, 10) || 0;
356
-
457
+
357
458
  if (!sourceElement.eventsInterval) {
358
459
  sourceElement.eventsInterval = {};
359
460
  }
360
-
461
+
361
462
  const currentInterval = sourceElement.eventsInterval[prefix];
362
463
 
363
464
  if (intervalMs > 0) {
364
465
  // Start or update interval
365
466
  if (!currentInterval || currentInterval.delay !== intervalMs) {
366
467
  if (currentInterval) clearInterval(currentInterval.id);
367
-
468
+
368
469
  sourceElement.eventsInterval[prefix] = {
369
470
  delay: intervalMs,
370
471
  id: setInterval(() => {
@@ -401,7 +502,7 @@ const CoCreateEvents = {
401
502
 
402
503
  // once
403
504
  const onceAttr = sourceElement.getAttribute(`${prefix}-once`);
404
- if (onceAttr !== null) {
505
+ if (onceAttr !== null) {
405
506
  if (!sourceElement.eventsOnce) {
406
507
  sourceElement.eventsOnce = [prefix];
407
508
  } else if (sourceElement.eventsOnce.includes(prefix)) {
@@ -412,7 +513,9 @@ const CoCreateEvents = {
412
513
  }
413
514
 
414
515
  // --- Resolve Targets ---
415
- const querySelector = sourceElement.getAttribute(`${prefix}-query`);
516
+ // const querySelector = sourceElement.getAttribute(`${prefix}-query`);
517
+ const querySelector =
518
+ sourceElement.attributes[`${prefix}-query`]?.value;
416
519
  let targetElements = [sourceElement];
417
520
 
418
521
  if (querySelector || params) {
@@ -440,6 +543,11 @@ const CoCreateEvents = {
440
543
  );
441
544
  },
442
545
 
546
+ /**
547
+ *
548
+ * @public
549
+ * @environment client
550
+ */
443
551
  setValue: async function (rootElement, sourceElement, targetElement, prefix, events) {
444
552
  // Handle Mouseout toggle logic
445
553
  if (events && events.includes("mouseout")) {
@@ -457,28 +565,62 @@ const CoCreateEvents = {
457
565
 
458
566
  const deactivate = (rootElement !== sourceElement);
459
567
 
460
- // Iterate Attributes
568
+ // Expand the prefix object in place, preserving attribute order.
569
+ const attributes = [];
461
570
  for (const attribute of sourceElement.attributes) {
571
+ if (attribute.name === prefix) {
572
+ const rawValue = attribute.value?.trim();
573
+ let assignments = null;
574
+ let assignmentsFromAst = false;
575
+
576
+ // An empty prefix remains an initialization marker.
577
+ if (!rawValue) continue;
578
+ if (rawValue?.startsWith("$")) {
579
+ assignments = await sourceElement.getAttributeAsync(attribute.name);
580
+ assignmentsFromAst = true;
581
+ } else if (rawValue.startsWith("{")) {
582
+ assignments = JSON.parse(rawValue);
583
+ } else {
584
+ continue;
585
+ }
586
+ if (!assignments || typeof assignments !== 'object') continue;
587
+
588
+ for (const [name, value] of Object.entries(assignments)) {
589
+ attributes.push({
590
+ name: `${prefix}.${name}`,
591
+ value,
592
+ fromObject: !assignmentsFromAst
593
+ });
594
+ }
595
+ } else {
596
+ attributes.push(attribute);
597
+ }
598
+ }
599
+
600
+ // Execute both forms through the existing assignment handlers.
601
+ for (const attribute of attributes) {
462
602
  const name = attribute.name;
463
-
603
+
464
604
  // Optimization: Skip if shorter than prefix + dot + min char
465
605
  if (name.length <= prefix.length + 1) continue;
466
-
606
+
467
607
  // STRICT RULE: Only process attributes with DOT separator.
468
608
  // All options use Dash, so they will be ignored here.
469
609
  if (!name.startsWith(prefix) || name[prefix.length] !== '.') continue;
470
610
 
471
611
  // Extract target name (e.g., 'value', 'style', 'src', 'data-something')
472
- const targetName = name.substring(prefix.length + 1);
473
-
474
- // Get Value
475
- let value = sourceElement.getAttribute(name);
476
- if (value === "$value" && sourceElement.getValue) {
477
- value = await sourceElement.getValue();
478
- }
612
+ let targetName = name.substring(prefix.length + 1);
613
+ const explicitProperty = targetName.startsWith("$");
479
614
 
480
- // Parse CSV for rotation
481
615
  let values = [];
616
+ const value = attribute.fromObject
617
+ ? await astAsync({
618
+ executeAST: attribute.value,
619
+ node: sourceElement,
620
+ sandbox: { $this: sourceElement }
621
+ })
622
+ : sourceElement.getAttribute(name);
623
+ // Parse CSV for rotation
482
624
  if (typeof value === 'string') {
483
625
  values = value.split(',').map(v => v.trim());
484
626
  } else if (Array.isArray(value)) {
@@ -486,18 +628,25 @@ const CoCreateEvents = {
486
628
  } else {
487
629
  values = [value];
488
630
  }
631
+ // Object values and dotted attribute values resolve through AST.
489
632
 
490
633
  let oldValue = "";
491
634
  let newValue = "";
492
635
 
493
636
  switch (targetName) {
637
+ case 'type':
638
+ oldValue = targetElement.getAttribute('type') || '';
639
+ newValue = this.__getNextValue(values, oldValue, deactivate);
640
+ targetElement.setAttribute('type', newValue);
641
+ break;
642
+
494
643
  case 'style':
495
644
  if (targetElement.getAttribute("style")) {
496
645
  // Normalize style string for comparison
497
646
  const styles = targetElement.getAttribute("style")
498
647
  .split(";")
499
648
  .map(x => x.trim().replace(/\s/g, ""));
500
-
649
+
501
650
  oldValue = values.find(x => styles.includes(x.replace(/\s/g, ""))) || "";
502
651
  }
503
652
  newValue = this.__getNextValue(values, oldValue, deactivate);
@@ -527,7 +676,7 @@ const CoCreateEvents = {
527
676
 
528
677
  if (oldValue) {
529
678
  oldValue.split(" ").forEach(c => targetElement.classList.remove(c));
530
- if (values.length === 1 && !newValue) return;
679
+ if (values.length === 1 && !newValue) return;
531
680
  }
532
681
 
533
682
  if (newValue) {
@@ -537,26 +686,60 @@ const CoCreateEvents = {
537
686
 
538
687
  case 'insertadjacenthtml':
539
688
  case 'insertadjacenttext':
540
- case 'insertAdjacentHTML':
689
+ case 'insertAdjacentHTML':
541
690
  case 'insertAdjacentText':
542
- const position = sourceElement.getAttribute(name);;
543
- if (!position) continue;
691
+ if (!value) continue;
692
+ const position = String(value).toLowerCase();
544
693
 
545
694
  let content = "";
546
- if (sourceElement.getValue) {
547
- content = await sourceElement.getValue();
695
+ if (sourceElement.hasAttribute(`${prefix}-value`)) {
696
+ content = sourceElement.getAttribute(`${prefix}-value`);
697
+ } else {
698
+ const contentSelector = sourceElement.attributes
699
+ .getNamedItem(`${prefix}-element`)?.value;
700
+ let contentSource = sourceElement;
701
+ if (contentSelector !== undefined) {
702
+ [contentSource] = queryElements({
703
+ element: sourceElement,
704
+ prefix,
705
+ selector: contentSelector
706
+ });
707
+ if (!contentSource) continue;
708
+ }
709
+ if (contentSource.getValue) content = contentSource.getValue();
548
710
  }
549
-
550
- // Check for CoCreate Rich Text integration
551
- let domTextEditor = targetElement.parentElement?.closest("[contenteditable]");
552
-
553
- if (domTextEditor && typeof CoCreate !== 'undefined' && CoCreate.text) {
554
- CoCreate.text.insertAdjacentElement({
555
- domTextEditor,
556
- position,
557
- target: targetElement,
558
- elementValue: content
559
- });
711
+ if (content && typeof content.then === 'function') {
712
+ content = await content;
713
+ }
714
+ content ??= "";
715
+
716
+ // Resolve adjacency to canonical source coordinates for editors.
717
+ const currentEditor = targetElement.editor;
718
+ const editorDetails = typeof currentEditor?.getStart === "function"
719
+ ? currentEditor : targetElement.editorDetails;
720
+ const editorElement = editorDetails?.element || editorDetails?.editorElement;
721
+ if (editorElement?.editor?.updateText) {
722
+ const point = editorDetails.getInsertionPoint?.(position);
723
+ if (point) {
724
+ await point.editor.updateText({ start: point.offset, length: 0, value: String(content) });
725
+ break;
726
+ }
727
+ if (typeof editorDetails.getInsertionPoint === "function")
728
+ throw new RangeError("Editor insertion position is not valid for this element.");
729
+ const outerRange = editorDetails.getOuterRange?.();
730
+ const contentRange = editorDetails.getContentRange?.();
731
+ const legacyBoundary = {
732
+ beforebegin: "start", afterbegin: "contentStart",
733
+ beforeend: "contentEnd", afterend: "end"
734
+ }[position];
735
+ const start = position === "beforebegin" ? outerRange?.start ?? editorDetails.start
736
+ : position === "afterbegin" ? contentRange?.start ?? editorDetails.contentStart
737
+ : position === "beforeend" ? contentRange?.end ?? editorDetails.contentEnd
738
+ : position === "afterend" ? outerRange?.end ?? editorDetails.end
739
+ : undefined;
740
+ if (!legacyBoundary || !Number.isInteger(start))
741
+ throw new RangeError("Editor insertion requires a current source range for the target.");
742
+ await editorElement.editor.updateText({ start, length: 0, value: String(content) });
560
743
  } else {
561
744
  const isHtml = targetName.toLowerCase().includes('html');
562
745
  if (isHtml) {
@@ -567,6 +750,30 @@ const CoCreateEvents = {
567
750
  }
568
751
  break;
569
752
 
753
+ case 'insertadjacentelement':
754
+ case 'insertAdjacentElement':
755
+ const elementPosition = value;
756
+ const elementSelector =
757
+ sourceElement.attributes.getNamedItem(`${prefix}-element`)?.value;
758
+ if (!elementPosition || !elementSelector) continue;
759
+
760
+ const elementsToInsert = queryElements({
761
+ element: sourceElement,
762
+ prefix,
763
+ selector: elementSelector
764
+ });
765
+ const elementToInsert = elementsToInsert[0];
766
+ if (
767
+ elementToInsert &&
768
+ typeof targetElement.insertAdjacentElement === 'function'
769
+ ) {
770
+ targetElement.insertAdjacentElement(
771
+ elementPosition,
772
+ elementToInsert
773
+ );
774
+ }
775
+ break;
776
+
570
777
  case 'value':
571
778
  if (targetElement.getValue) {
572
779
  oldValue = await targetElement.getValue();
@@ -578,7 +785,14 @@ const CoCreateEvents = {
578
785
  newValue = this.__getNextValue(values, oldValue, deactivate);
579
786
 
580
787
  if (targetElement.setValue) {
581
- targetElement.setValue(newValue);
788
+ if (
789
+ targetElement === sourceElement &&
790
+ ["input", "change"].includes(prefix)
791
+ ) {
792
+ targetElement.setValue(newValue, true);
793
+ } else {
794
+ targetElement.setValue(newValue);
795
+ }
582
796
  } else {
583
797
  targetElement.value = newValue;
584
798
  }
@@ -586,25 +800,54 @@ const CoCreateEvents = {
586
800
 
587
801
  default:
588
802
  // Generic handling: Try Property first, then Attribute
589
-
590
- // 1. Try Property
591
- if (targetElement[targetName] !== undefined) {
592
- oldValue = targetElement[targetName];
803
+
804
+ // $ always selects a property, including one not yet defined.
805
+ let propertyName;
806
+ let propertyTarget = targetElement;
807
+ let propertyValue;
808
+ if (explicitProperty || (
809
+ propertyName = resolveProperty(targetElement, targetName)
810
+ ) !== undefined) {
811
+ if (explicitProperty) {
812
+ const propertyPath = resolvePropertyPath(
813
+ targetElement,
814
+ targetName.substring(1)
815
+ );
816
+ if (propertyPath) {
817
+ propertyTarget = propertyPath.target;
818
+ propertyName = propertyPath.key;
819
+ propertyValue = propertyPath.value;
820
+ } else {
821
+ targetName = targetName.substring(1);
822
+ propertyName = resolveProperty(targetElement, targetName);
823
+ }
824
+ }
825
+ targetName = propertyName ?? targetName;
826
+ propertyValue ??= propertyTarget[targetName];
827
+ oldValue = propertyValue;
593
828
  if (!values.includes(oldValue) && typeof oldValue !== 'function') oldValue = "";
594
-
829
+
595
830
  newValue = this.__getNextValue(values, oldValue, deactivate);
596
831
 
597
- if (typeof targetElement[targetName] === 'function') {
598
- targetElement[targetName](newValue);
832
+ if (typeof propertyValue === 'function') {
833
+ // A non-$ method binding with value=false disables
834
+ // the action. Explicit $ bindings may still
835
+ // intentionally pass false as an argument.
836
+ if (
837
+ explicitProperty ||
838
+ (newValue !== false && newValue !== "false")
839
+ ) {
840
+ propertyValue.call(propertyTarget, newValue);
841
+ }
599
842
  } else {
600
- targetElement[targetName] = newValue;
843
+ propertyTarget[targetName] = newValue;
601
844
  }
602
- }
845
+ }
603
846
  // 2. Fallback to Attribute
604
847
  else {
605
848
  oldValue = targetElement.getAttribute(targetName);
606
849
  if (!values.includes(oldValue)) oldValue = "";
607
-
850
+
608
851
  newValue = this.__getNextValue(values, oldValue, deactivate);
609
852
 
610
853
  // Handle Namespaced Attributes (e.g. svg:href) if encoded in name
@@ -615,6 +858,11 @@ const CoCreateEvents = {
615
858
  }
616
859
  },
617
860
 
861
+ /**
862
+ *
863
+ * @public
864
+ * @environment client
865
+ */
618
866
  __getNextValue: function (values, val, deactivate) {
619
867
  if (deactivate) return "";
620
868
  const size = values.length;
@@ -629,4 +877,50 @@ const CoCreateEvents = {
629
877
 
630
878
  CoCreateEvents.init();
631
879
 
632
- export default CoCreateEvents;
880
+ export default CoCreateEvents;
881
+
882
+ /**
883
+ *
884
+ * @name event-name
885
+ * @kind member
886
+ * @attribute
887
+ * @environment client
888
+ */
889
+
890
+ /**
891
+ *
892
+ * @name style
893
+ * @kind member
894
+ * @attribute
895
+ * @environment client
896
+ */
897
+
898
+ /**
899
+ *
900
+ * @name type
901
+ * @kind member
902
+ * @attribute
903
+ * @environment client
904
+ */
905
+
906
+ /**
907
+ * A simple events component in vanilla javascript. Easily configured using HTML5 attributes and/or JavaScript API.
908
+ *
909
+ * @module events
910
+ * @environment client
911
+ */
912
+
913
+ /**
914
+ * Declarative selectors recognized by this module.
915
+ *
916
+ * @name declarative-selectors
917
+ * @kind member
918
+ * @selectors
919
+ * @environment client
920
+ * @example
921
+ * ```json
922
+ * [
923
+ * "[event-name]"
924
+ * ]
925
+ * ```
926
+ */