@builder.io/sdk-svelte 0.0.7 → 0.0.9-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.
Files changed (48) hide show
  1. package/package/--package.json +2 -3
  2. package/package/blocks/button/button.svelte +35 -3
  3. package/package/blocks/form/form.svelte +29 -1
  4. package/package/blocks/img/img.svelte +29 -1
  5. package/package/blocks/input/input.svelte +29 -1
  6. package/package/blocks/section/section.svelte +30 -2
  7. package/package/blocks/select/select.svelte +29 -1
  8. package/package/blocks/submit-button/submit-button.svelte +33 -2
  9. package/package/blocks/symbol/symbol.svelte +29 -1
  10. package/package/blocks/textarea/textarea.svelte +36 -2
  11. package/package/blocks/video/video.svelte +30 -2
  12. package/package/components/render-block/render-block.svelte +29 -8
  13. package/package/components/render-content/render-content.svelte +24 -3
  14. package/package/components/render-content/render-content.svelte.d.ts +4 -0
  15. package/package/functions/evaluate.d.ts +2 -1
  16. package/package/functions/evaluate.js +8 -5
  17. package/package/functions/event-handler-name.js +1 -4
  18. package/package/functions/get-block-actions-handler.d.ts +5 -2
  19. package/package/functions/get-block-actions-handler.js +7 -8
  20. package/package/functions/get-block-actions.js +2 -2
  21. package/package/functions/get-builder-search-params/index.d.ts +1 -1
  22. package/package/functions/track.d.ts +6 -1
  23. package/package/functions/track.js +4 -0
  24. package/package/scripts/init-editing.d.ts +4 -1
  25. package/package/scripts/init-editing.js +7 -1
  26. package/package.json +2 -2
  27. package/src/blocks/button/button.svelte +41 -2
  28. package/src/blocks/form/form.svelte +36 -1
  29. package/src/blocks/img/img.svelte +36 -1
  30. package/src/blocks/input/input.svelte +36 -1
  31. package/src/blocks/section/section.svelte +36 -1
  32. package/src/blocks/select/select.svelte +36 -1
  33. package/src/blocks/submit-button/submit-button.svelte +39 -1
  34. package/src/blocks/symbol/symbol.svelte +36 -1
  35. package/src/blocks/textarea/textarea.svelte +42 -1
  36. package/src/blocks/video/video.svelte +36 -1
  37. package/src/components/render-block/render-block.svelte +34 -8
  38. package/src/components/render-content/render-content.svelte +28 -3
  39. package/src/functions/evaluate.ts +11 -6
  40. package/src/functions/event-handler-name.ts +1 -6
  41. package/src/functions/get-block-actions-handler.ts +10 -9
  42. package/src/functions/get-block-actions.ts +2 -2
  43. package/src/functions/get-builder-search-params/index.ts +1 -1
  44. package/src/functions/track.ts +13 -1
  45. package/src/scripts/init-editing.ts +16 -1
  46. package/package/functions/mark-mutable.d.ts +0 -2
  47. package/package/functions/mark-mutable.js +0 -6
  48. package/src/functions/mark-mutable.ts +0 -7
@@ -1,6 +1,6 @@
1
1
  import { isBrowser } from './is-browser.js';
2
2
  import { isEditing } from './is-editing.js';
3
- export function evaluate({ code, context, state, event, }) {
3
+ export function evaluate({ code, context, state, event, isExpression = true, }) {
4
4
  if (code === '') {
5
5
  console.warn('Skipping evaluation of empty code block.');
6
6
  return;
@@ -12,14 +12,17 @@ export function evaluate({ code, context, state, event, }) {
12
12
  };
13
13
  // Be able to handle simple expressions like "state.foo" or "1 + 1"
14
14
  // as well as full blocks like "var foo = "bar"; return foo"
15
- const useReturn = !(code.includes(';') ||
16
- code.includes(' return ') ||
17
- code.trim().startsWith('return '));
15
+ const useReturn =
16
+ // we disable this for cases where we definitely don't want a return
17
+ isExpression &&
18
+ !(code.includes(';') ||
19
+ code.includes(' return ') ||
20
+ code.trim().startsWith('return '));
18
21
  const useCode = useReturn ? `return (${code});` : code;
19
22
  try {
20
23
  return new Function('builder', 'Builder' /* <- legacy */, 'state', 'context', 'event', useCode)(builder, builder, state, context, event);
21
24
  }
22
25
  catch (e) {
23
- console.warn('Builder custom code error: \n While Evaluating: \n ', useCode, '\n', e.message || e);
26
+ console.warn('Builder custom code error: \n While Evaluating: \n ', useCode, '\n', e);
24
27
  }
25
28
  }
@@ -1,4 +1 @@
1
- function capitalizeFirstLetter(string) {
2
- return string.charAt(0).toUpperCase() + string.slice(1);
3
- }
4
- export const getEventHandlerName = (key) => `on${capitalizeFirstLetter(key)}`;
1
+ export const getEventHandlerName = (key) => `on:${key.toLowerCase()}`;
@@ -1,5 +1,8 @@
1
1
  import type { BuilderContextInterface } from '../context/types.js';
2
2
  import type { BuilderBlock } from '../types/builder-block.js';
3
- export declare function crateEventHandler(value: string, options: {
3
+ declare type Options = {
4
4
  block: BuilderBlock;
5
- } & Pick<BuilderContextInterface, 'state' | 'context'>): (event: Event) => any;
5
+ } & Pick<BuilderContextInterface, 'state' | 'context'>;
6
+ declare type EventHandler = (event: Event) => any;
7
+ export declare const createEventHandler: (value: string, options: Options) => EventHandler;
8
+ export {};
@@ -1,9 +1,8 @@
1
1
  import { evaluate } from './evaluate.js';
2
- export function crateEventHandler(value, options) {
3
- return (event) => evaluate({
4
- code: value,
5
- context: options.context,
6
- state: options.state,
7
- event,
8
- });
9
- }
2
+ export const createEventHandler = (value, options) => (event) => evaluate({
3
+ code: value,
4
+ context: options.context,
5
+ state: options.state,
6
+ event,
7
+ isExpression: false,
8
+ });
@@ -1,5 +1,5 @@
1
1
  import { getEventHandlerName } from './event-handler-name.js';
2
- import { crateEventHandler } from './get-block-actions-handler.js';
2
+ import { createEventHandler } from './get-block-actions-handler.js';
3
3
  export function getBlockActions(options) {
4
4
  const obj = {};
5
5
  const optionActions = options.block.actions ?? {};
@@ -9,7 +9,7 @@ export function getBlockActions(options) {
9
9
  continue;
10
10
  }
11
11
  const value = optionActions[key];
12
- obj[getEventHandlerName(key)] = crateEventHandler(value, options);
12
+ obj[getEventHandlerName(key)] = createEventHandler(value, options);
13
13
  }
14
14
  return obj;
15
15
  }
@@ -1,4 +1,4 @@
1
- declare type QueryObject = Record<string, string>;
1
+ declare type QueryObject = Record<string, string | string[]>;
2
2
  export declare const convertSearchParamsToQueryObject: (searchParams: URLSearchParams) => QueryObject;
3
3
  export declare const getBuilderSearchParams: (_options: QueryObject | URLSearchParams | undefined) => QueryObject;
4
4
  export declare const getBuilderSearchParamsFromWindow: () => QueryObject;
@@ -1,6 +1,11 @@
1
1
  import type { CanTrack } from '../types/can-track.js';
2
2
  interface Event {
3
- type: 'click' | 'impression';
3
+ /**
4
+ * The type of your event.
5
+ *
6
+ * Examples: `click`, `conversion`, `pageview`, `impression`
7
+ */
8
+ type: string;
4
9
  data: {
5
10
  /**
6
11
  * (Optional) The content's ID. Useful if this event pertains to a specific piece of content.
@@ -24,6 +24,10 @@ const createEvent = async ({ type: eventType, canTrack, apiKey, metadata, ...pro
24
24
  },
25
25
  });
26
26
  export async function _track(eventProps) {
27
+ if (!eventProps.apiKey) {
28
+ console.error('[Builder.io]: Missing API key for track call. Please provide your API key.');
29
+ return;
30
+ }
27
31
  if (!eventProps.canTrack) {
28
32
  return;
29
33
  }
@@ -1,2 +1,5 @@
1
1
  export declare const registerInsertMenu: () => void;
2
- export declare const setupBrowserForEditing: () => void;
2
+ export declare const setupBrowserForEditing: (options?: {
3
+ includeRefs?: boolean;
4
+ locale?: string;
5
+ }) => void;
@@ -22,7 +22,7 @@ export const registerInsertMenu = () => {
22
22
  });
23
23
  };
24
24
  let isSetupForEditing = false;
25
- export const setupBrowserForEditing = () => {
25
+ export const setupBrowserForEditing = (options = {}) => {
26
26
  if (isSetupForEditing) {
27
27
  return;
28
28
  }
@@ -42,6 +42,12 @@ export const setupBrowserForEditing = () => {
42
42
  supportsCustomBreakpoints: true,
43
43
  },
44
44
  }, '*');
45
+ window.parent?.postMessage({
46
+ type: 'builder.updateContent',
47
+ data: {
48
+ options,
49
+ },
50
+ }, '*');
45
51
  window.addEventListener('message', ({ data }) => {
46
52
  if (!data?.type) {
47
53
  return;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@builder.io/sdk-svelte",
3
3
  "description": "Builder.io SDK for Svelte",
4
- "version": "0.0.7",
4
+ "version": "0.0.9-0",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "package",
@@ -15,7 +15,7 @@
15
15
  },
16
16
  "main": "./package/index.js",
17
17
  "module": "./package/index.js",
18
- "svelte": "./src/index.ts",
18
+ "svelte": "./package/index.js",
19
19
  "exports": {
20
20
  "./src": {
21
21
  "import": "./src/index.js",
@@ -8,6 +8,40 @@
8
8
  </script>
9
9
 
10
10
  <script lang="ts">
11
+ const isEvent = (attr) => attr.startsWith("on:");
12
+ const isNonEvent = (attr) => !attr.startsWith("on:");
13
+
14
+ const filterAttrs = (attrs, filter) => {
15
+ const validAttr = {};
16
+ Object.keys(attrs).forEach((attr) => {
17
+ if (filter(attr)) {
18
+ validAttr[attr] = attrs[attr];
19
+ }
20
+ });
21
+ return validAttr;
22
+ };
23
+
24
+ const setAttrs = (node, attrs) => {
25
+ const attrKeys = Object.keys(attrs);
26
+
27
+ const setup = (attr) => node.addEventListener(attr.substr(3), attrs[attr]);
28
+ const teardown = (attr) =>
29
+ node.removeEventListener(attr.substr(3), attrs[attr]);
30
+
31
+ attrKeys.map(setup);
32
+
33
+ return {
34
+ update(attrs) {
35
+ const attrKeys = Object.keys(attrs);
36
+ attrKeys.map(teardown);
37
+ attrKeys.map(setup);
38
+ },
39
+ destroy() {
40
+ attrKeys.map(teardown);
41
+ },
42
+ };
43
+ };
44
+
11
45
  export let attributes: ButtonProps["attributes"];
12
46
  export let text: ButtonProps["text"];
13
47
  export let link: ButtonProps["link"];
@@ -17,14 +51,19 @@
17
51
  {#if link}
18
52
  <a
19
53
  role="button"
20
- {...attributes}
54
+ {...filterAttrs(attributes, isNonEvent)}
21
55
  href={link}
22
56
  target={openLinkInNewTab ? "_blank" : undefined}
57
+ use:setAttrs={filterAttrs(attributes, isEvent)}
23
58
  >
24
59
  {text}
25
60
  </a>
26
61
  {:else}
27
- <button class="button" {...attributes}>
62
+ <button
63
+ class="button"
64
+ {...filterAttrs(attributes, isNonEvent)}
65
+ use:setAttrs={filterAttrs(attributes, isEvent)}
66
+ >
28
67
  {text}
29
68
  </button>
30
69
  {/if}
@@ -64,6 +64,40 @@
64
64
  import BuilderBlocks from "../../components/render-blocks.svelte";
65
65
  import { isEditing } from "../../functions/is-editing.js";
66
66
 
67
+ const isEvent = (attr) => attr.startsWith("on:");
68
+ const isNonEvent = (attr) => !attr.startsWith("on:");
69
+
70
+ const filterAttrs = (attrs, filter) => {
71
+ const validAttr = {};
72
+ Object.keys(attrs).forEach((attr) => {
73
+ if (filter(attr)) {
74
+ validAttr[attr] = attrs[attr];
75
+ }
76
+ });
77
+ return validAttr;
78
+ };
79
+
80
+ const setAttrs = (node, attrs) => {
81
+ const attrKeys = Object.keys(attrs);
82
+
83
+ const setup = (attr) => node.addEventListener(attr.substr(3), attrs[attr]);
84
+ const teardown = (attr) =>
85
+ node.removeEventListener(attr.substr(3), attrs[attr]);
86
+
87
+ attrKeys.map(setup);
88
+
89
+ return {
90
+ update(attrs) {
91
+ const attrKeys = Object.keys(attrs);
92
+ attrKeys.map(teardown);
93
+ attrKeys.map(setup);
94
+ },
95
+ destroy() {
96
+ attrKeys.map(teardown);
97
+ },
98
+ };
99
+ };
100
+
67
101
  export let previewState: FormProps["previewState"];
68
102
  export let sendWithJs: FormProps["sendWithJs"];
69
103
  export let sendSubmissionsTo: FormProps["sendSubmissionsTo"];
@@ -296,7 +330,8 @@
296
330
  on:submit={(event) => {
297
331
  onSubmit(event);
298
332
  }}
299
- {...attributes}
333
+ {...filterAttrs(attributes, isNonEvent)}
334
+ use:setAttrs={filterAttrs(attributes, isEvent)}
300
335
  >
301
336
  {#if builderBlock && builderBlock.children}
302
337
  {#each builderBlock?.children as block}
@@ -21,6 +21,40 @@
21
21
  <script lang="ts">
22
22
  import { isEditing } from "../../functions/is-editing.js";
23
23
 
24
+ const isEvent = (attr) => attr.startsWith("on:");
25
+ const isNonEvent = (attr) => !attr.startsWith("on:");
26
+
27
+ const filterAttrs = (attrs, filter) => {
28
+ const validAttr = {};
29
+ Object.keys(attrs).forEach((attr) => {
30
+ if (filter(attr)) {
31
+ validAttr[attr] = attrs[attr];
32
+ }
33
+ });
34
+ return validAttr;
35
+ };
36
+
37
+ const setAttrs = (node, attrs) => {
38
+ const attrKeys = Object.keys(attrs);
39
+
40
+ const setup = (attr) => node.addEventListener(attr.substr(3), attrs[attr]);
41
+ const teardown = (attr) =>
42
+ node.removeEventListener(attr.substr(3), attrs[attr]);
43
+
44
+ attrKeys.map(setup);
45
+
46
+ return {
47
+ update(attrs) {
48
+ const attrKeys = Object.keys(attrs);
49
+ attrKeys.map(teardown);
50
+ attrKeys.map(setup);
51
+ },
52
+ destroy() {
53
+ attrKeys.map(teardown);
54
+ },
55
+ };
56
+ };
57
+
24
58
  export let backgroundSize: ImgProps["backgroundSize"];
25
59
  export let backgroundPosition: ImgProps["backgroundPosition"];
26
60
  export let imgSrc: ImgProps["imgSrc"];
@@ -47,5 +81,6 @@
47
81
  key={(isEditing() && imgSrc) || "default-key"}
48
82
  alt={altText}
49
83
  src={imgSrc || image}
50
- {...attributes}
84
+ {...filterAttrs(attributes, isNonEvent)}
85
+ use:setAttrs={filterAttrs(attributes, isEvent)}
51
86
  />
@@ -13,6 +13,40 @@
13
13
  <script lang="ts">
14
14
  import { isEditing } from "../../functions/is-editing.js";
15
15
 
16
+ const isEvent = (attr) => attr.startsWith("on:");
17
+ const isNonEvent = (attr) => !attr.startsWith("on:");
18
+
19
+ const filterAttrs = (attrs, filter) => {
20
+ const validAttr = {};
21
+ Object.keys(attrs).forEach((attr) => {
22
+ if (filter(attr)) {
23
+ validAttr[attr] = attrs[attr];
24
+ }
25
+ });
26
+ return validAttr;
27
+ };
28
+
29
+ const setAttrs = (node, attrs) => {
30
+ const attrKeys = Object.keys(attrs);
31
+
32
+ const setup = (attr) => node.addEventListener(attr.substr(3), attrs[attr]);
33
+ const teardown = (attr) =>
34
+ node.removeEventListener(attr.substr(3), attrs[attr]);
35
+
36
+ attrKeys.map(setup);
37
+
38
+ return {
39
+ update(attrs) {
40
+ const attrKeys = Object.keys(attrs);
41
+ attrKeys.map(teardown);
42
+ attrKeys.map(setup);
43
+ },
44
+ destroy() {
45
+ attrKeys.map(teardown);
46
+ },
47
+ };
48
+ };
49
+
16
50
  export let attributes: FormInputProps["attributes"];
17
51
  export let defaultValue: FormInputProps["defaultValue"];
18
52
  export let placeholder: FormInputProps["placeholder"];
@@ -23,7 +57,7 @@
23
57
  </script>
24
58
 
25
59
  <input
26
- {...attributes}
60
+ {...filterAttrs(attributes, isNonEvent)}
27
61
  key={isEditing() && defaultValue ? defaultValue : "default-key"}
28
62
  {placeholder}
29
63
  {type}
@@ -31,4 +65,5 @@
31
65
  {value}
32
66
  {defaultValue}
33
67
  {required}
68
+ use:setAttrs={filterAttrs(attributes, isEvent)}
34
69
  />
@@ -8,6 +8,40 @@
8
8
  </script>
9
9
 
10
10
  <script lang="ts">
11
+ const isEvent = (attr) => attr.startsWith("on:");
12
+ const isNonEvent = (attr) => !attr.startsWith("on:");
13
+
14
+ const filterAttrs = (attrs, filter) => {
15
+ const validAttr = {};
16
+ Object.keys(attrs).forEach((attr) => {
17
+ if (filter(attr)) {
18
+ validAttr[attr] = attrs[attr];
19
+ }
20
+ });
21
+ return validAttr;
22
+ };
23
+
24
+ const setAttrs = (node, attrs) => {
25
+ const attrKeys = Object.keys(attrs);
26
+
27
+ const setup = (attr) => node.addEventListener(attr.substr(3), attrs[attr]);
28
+ const teardown = (attr) =>
29
+ node.removeEventListener(attr.substr(3), attrs[attr]);
30
+
31
+ attrKeys.map(setup);
32
+
33
+ return {
34
+ update(attrs) {
35
+ const attrKeys = Object.keys(attrs);
36
+ attrKeys.map(teardown);
37
+ attrKeys.map(setup);
38
+ },
39
+ destroy() {
40
+ attrKeys.map(teardown);
41
+ },
42
+ };
43
+ };
44
+
11
45
  export let attributes: SectionProps["attributes"];
12
46
  export let maxWidth: SectionProps["maxWidth"];
13
47
 
@@ -28,7 +62,8 @@
28
62
  maxWidth: maxWidth,
29
63
  }
30
64
  : undefined}
31
- {...attributes}
65
+ {...filterAttrs(attributes, isNonEvent)}
66
+ use:setAttrs={filterAttrs(attributes, isEvent)}
32
67
  >
33
68
  <slot />
34
69
  </section>
@@ -14,6 +14,40 @@
14
14
  <script lang="ts">
15
15
  import { isEditing } from "../../functions/is-editing.js";
16
16
 
17
+ const isEvent = (attr) => attr.startsWith("on:");
18
+ const isNonEvent = (attr) => !attr.startsWith("on:");
19
+
20
+ const filterAttrs = (attrs, filter) => {
21
+ const validAttr = {};
22
+ Object.keys(attrs).forEach((attr) => {
23
+ if (filter(attr)) {
24
+ validAttr[attr] = attrs[attr];
25
+ }
26
+ });
27
+ return validAttr;
28
+ };
29
+
30
+ const setAttrs = (node, attrs) => {
31
+ const attrKeys = Object.keys(attrs);
32
+
33
+ const setup = (attr) => node.addEventListener(attr.substr(3), attrs[attr]);
34
+ const teardown = (attr) =>
35
+ node.removeEventListener(attr.substr(3), attrs[attr]);
36
+
37
+ attrKeys.map(setup);
38
+
39
+ return {
40
+ update(attrs) {
41
+ const attrKeys = Object.keys(attrs);
42
+ attrKeys.map(teardown);
43
+ attrKeys.map(setup);
44
+ },
45
+ destroy() {
46
+ attrKeys.map(teardown);
47
+ },
48
+ };
49
+ };
50
+
17
51
  export let attributes: FormSelectProps["attributes"];
18
52
  export let value: FormSelectProps["value"];
19
53
  export let defaultValue: FormSelectProps["defaultValue"];
@@ -22,11 +56,12 @@
22
56
  </script>
23
57
 
24
58
  <select
25
- {...attributes}
59
+ {...filterAttrs(attributes, isNonEvent)}
26
60
  {value}
27
61
  key={isEditing() && defaultValue ? defaultValue : "default-key"}
28
62
  {defaultValue}
29
63
  {name}
64
+ use:setAttrs={filterAttrs(attributes, isEvent)}
30
65
  >
31
66
  {#each options as option}
32
67
  <option value={option.value}>{option.name || option.value}</option>
@@ -6,10 +6,48 @@
6
6
  </script>
7
7
 
8
8
  <script lang="ts">
9
+ const isEvent = (attr) => attr.startsWith("on:");
10
+ const isNonEvent = (attr) => !attr.startsWith("on:");
11
+
12
+ const filterAttrs = (attrs, filter) => {
13
+ const validAttr = {};
14
+ Object.keys(attrs).forEach((attr) => {
15
+ if (filter(attr)) {
16
+ validAttr[attr] = attrs[attr];
17
+ }
18
+ });
19
+ return validAttr;
20
+ };
21
+
22
+ const setAttrs = (node, attrs) => {
23
+ const attrKeys = Object.keys(attrs);
24
+
25
+ const setup = (attr) => node.addEventListener(attr.substr(3), attrs[attr]);
26
+ const teardown = (attr) =>
27
+ node.removeEventListener(attr.substr(3), attrs[attr]);
28
+
29
+ attrKeys.map(setup);
30
+
31
+ return {
32
+ update(attrs) {
33
+ const attrKeys = Object.keys(attrs);
34
+ attrKeys.map(teardown);
35
+ attrKeys.map(setup);
36
+ },
37
+ destroy() {
38
+ attrKeys.map(teardown);
39
+ },
40
+ };
41
+ };
42
+
9
43
  export let attributes: ButtonProps["attributes"];
10
44
  export let text: ButtonProps["text"];
11
45
  </script>
12
46
 
13
- <button type="submit" {...attributes}>
47
+ <button
48
+ type="submit"
49
+ {...filterAttrs(attributes, isNonEvent)}
50
+ use:setAttrs={filterAttrs(attributes, isEvent)}
51
+ >
14
52
  {text}
15
53
  </button>
@@ -31,6 +31,40 @@
31
31
  import BuilderContext from "../../context/builder.context.js";
32
32
  import { getContent } from "../../functions/get-content/index.js";
33
33
 
34
+ const isEvent = (attr) => attr.startsWith("on:");
35
+ const isNonEvent = (attr) => !attr.startsWith("on:");
36
+
37
+ const filterAttrs = (attrs, filter) => {
38
+ const validAttr = {};
39
+ Object.keys(attrs).forEach((attr) => {
40
+ if (filter(attr)) {
41
+ validAttr[attr] = attrs[attr];
42
+ }
43
+ });
44
+ return validAttr;
45
+ };
46
+
47
+ const setAttrs = (node, attrs) => {
48
+ const attrKeys = Object.keys(attrs);
49
+
50
+ const setup = (attr) => node.addEventListener(attr.substr(3), attrs[attr]);
51
+ const teardown = (attr) =>
52
+ node.removeEventListener(attr.substr(3), attrs[attr]);
53
+
54
+ attrKeys.map(setup);
55
+
56
+ return {
57
+ update(attrs) {
58
+ const attrKeys = Object.keys(attrs);
59
+ attrKeys.map(teardown);
60
+ attrKeys.map(setup);
61
+ },
62
+ destroy() {
63
+ attrKeys.map(teardown);
64
+ },
65
+ };
66
+ };
67
+
34
68
  export let symbol: SymbolProps["symbol"];
35
69
  export let attributes: SymbolProps["attributes"];
36
70
 
@@ -76,11 +110,12 @@
76
110
  </script>
77
111
 
78
112
  <div
79
- {...attributes}
113
+ {...filterAttrs(attributes, isNonEvent)}
80
114
  dataSet={{
81
115
  class: className,
82
116
  }}
83
117
  class={className}
118
+ use:setAttrs={filterAttrs(attributes, isEvent)}
84
119
  >
85
120
  <RenderContent
86
121
  apiKey={builderContext.apiKey}
@@ -9,6 +9,40 @@
9
9
  </script>
10
10
 
11
11
  <script lang="ts">
12
+ const isEvent = (attr) => attr.startsWith("on:");
13
+ const isNonEvent = (attr) => !attr.startsWith("on:");
14
+
15
+ const filterAttrs = (attrs, filter) => {
16
+ const validAttr = {};
17
+ Object.keys(attrs).forEach((attr) => {
18
+ if (filter(attr)) {
19
+ validAttr[attr] = attrs[attr];
20
+ }
21
+ });
22
+ return validAttr;
23
+ };
24
+
25
+ const setAttrs = (node, attrs) => {
26
+ const attrKeys = Object.keys(attrs);
27
+
28
+ const setup = (attr) => node.addEventListener(attr.substr(3), attrs[attr]);
29
+ const teardown = (attr) =>
30
+ node.removeEventListener(attr.substr(3), attrs[attr]);
31
+
32
+ attrKeys.map(setup);
33
+
34
+ return {
35
+ update(attrs) {
36
+ const attrKeys = Object.keys(attrs);
37
+ attrKeys.map(teardown);
38
+ attrKeys.map(setup);
39
+ },
40
+ destroy() {
41
+ attrKeys.map(teardown);
42
+ },
43
+ };
44
+ };
45
+
12
46
  export let attributes: TextareaProps["attributes"];
13
47
  export let placeholder: TextareaProps["placeholder"];
14
48
  export let name: TextareaProps["name"];
@@ -16,4 +50,11 @@
16
50
  export let defaultValue: TextareaProps["defaultValue"];
17
51
  </script>
18
52
 
19
- <textarea {...attributes} {placeholder} {name} {value} {defaultValue} />
53
+ <textarea
54
+ {...filterAttrs(attributes, isNonEvent)}
55
+ {placeholder}
56
+ {name}
57
+ {value}
58
+ {defaultValue}
59
+ use:setAttrs={filterAttrs(attributes, isEvent)}
60
+ />