@lowdefy/blocks-basic 0.0.0-experimental-20260928105334 → 0.0.0-experimental-20260928120643

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 (34) hide show
  1. package/dist/blocks/Anchor/Anchor.js +1 -1
  2. package/dist/blocks/Anchor/gallery.yaml +14 -14
  3. package/dist/blocks/Anchor/meta.js +4 -2
  4. package/dist/blocks/Anchor/tests/Anchor.e2e.yaml +1 -1
  5. package/dist/blocks/Anchor/tests.yaml +6 -6
  6. package/dist/blocks/Box/gallery.yaml +9 -9
  7. package/dist/blocks/ClickableHtml/ClickableHtml.js +9 -28
  8. package/dist/blocks/ClickableHtml/gallery.yaml +86 -0
  9. package/dist/blocks/ClickableHtml/meta.js +57 -1
  10. package/dist/blocks/ClickableHtml/tests/ClickableHtml.e2e.yaml +119 -0
  11. package/dist/blocks/ClickableHtml/tests.yaml +13 -0
  12. package/dist/blocks/DangerousHtml/DangerousHtml.js +19 -19
  13. package/dist/blocks/DangerousHtml/meta.js +13 -1
  14. package/dist/blocks/Dynamic/meta.js +4 -0
  15. package/dist/blocks/Html/gallery.yaml +28 -0
  16. package/dist/blocks/Html/meta.js +23 -1
  17. package/dist/blocks/Html/tests/Html.e2e.yaml +12 -0
  18. package/dist/blocks/Icon/Icon.js +21 -1
  19. package/dist/blocks/Icon/gallery.yaml +158 -64
  20. package/dist/blocks/Icon/meta.js +11 -4
  21. package/dist/blocks/Icon/tests/Icon.e2e.yaml +3 -3
  22. package/dist/blocks/Icon/tests.yaml +7 -7
  23. package/dist/blocks/Img/meta.js +2 -0
  24. package/dist/blocks/List/gallery.yaml +11 -11
  25. package/dist/blocks/PollingTimer/PollingTimer.js +120 -0
  26. package/dist/blocks/PollingTimer/e2e.js +21 -0
  27. package/dist/blocks/PollingTimer/gallery.yaml +190 -0
  28. package/dist/blocks/PollingTimer/meta.js +61 -0
  29. package/dist/blocks/PollingTimer/validateInterval.js +21 -0
  30. package/dist/blocks/Span/gallery.yaml +7 -7
  31. package/dist/blocks.js +1 -0
  32. package/dist/e2e.js +1 -0
  33. package/dist/metas.js +1 -0
  34. package/package.json +8 -5
@@ -40,7 +40,7 @@ const AnchorBlock = ({ blockId, classNames, events, components: { Icon, Link, Sh
40
40
  },
41
41
  events: events,
42
42
  properties: get(events, 'onClick.loading') ? {
43
- name: 'AiOutlineLoading3Quarters',
43
+ name: 'loading',
44
44
  spin: true
45
45
  } : icon,
46
46
  styles: {
@@ -68,7 +68,7 @@
68
68
  properties:
69
69
  title: Link with Icon
70
70
  url: https://lowdefy.com
71
- icon: AiOutlineLink
71
+ icon: link
72
72
  - id: icon_download
73
73
  type: Anchor
74
74
  layout:
@@ -76,7 +76,7 @@
76
76
  properties:
77
77
  title: Download
78
78
  url: https://lowdefy.com
79
- icon: AiOutlineDownload
79
+ icon: download
80
80
  - id: icon_external
81
81
  type: Anchor
82
82
  layout:
@@ -84,7 +84,7 @@
84
84
  properties:
85
85
  title: External Link
86
86
  url: https://lowdefy.com
87
- icon: AiOutlineExport
87
+ icon: SquareArrowOutUpRight
88
88
  - id: icon_mail
89
89
  type: Anchor
90
90
  layout:
@@ -92,7 +92,7 @@
92
92
  properties:
93
93
  title: Send Email
94
94
  url: https://lowdefy.com
95
- icon: AiOutlineMail
95
+ icon: mail
96
96
  - id: icon_github
97
97
  type: Anchor
98
98
  layout:
@@ -100,7 +100,7 @@
100
100
  properties:
101
101
  title: GitHub
102
102
  url: https://github.com/lowdefy/lowdefy
103
- icon: AiOutlineGithub
103
+ icon: GitBranch
104
104
  - id: icon_object
105
105
  type: Anchor
106
106
  layout:
@@ -109,7 +109,7 @@
109
109
  title: Colored Icon
110
110
  url: https://lowdefy.com
111
111
  icon:
112
- name: AiOutlineHeart
112
+ name: heart
113
113
  color: '#ff4d4f'
114
114
 
115
115
  - title: New Tab
@@ -130,7 +130,7 @@
130
130
  title: External Docs
131
131
  url: https://docs.lowdefy.com
132
132
  newTab: true
133
- icon: AiOutlineExport
133
+ icon: SquareArrowOutUpRight
134
134
 
135
135
  - title: Disabled
136
136
  blocks:
@@ -150,7 +150,7 @@
150
150
  title: Disabled with Icon
151
151
  url: https://lowdefy.com
152
152
  disabled: true
153
- icon: AiOutlineLock
153
+ icon: lock
154
154
  - id: enabled_link
155
155
  type: Anchor
156
156
  layout:
@@ -159,7 +159,7 @@
159
159
  title: Enabled Link
160
160
  url: https://lowdefy.com
161
161
  disabled: false
162
- icon: AiOutlineUnlock
162
+ icon: unlock
163
163
 
164
164
  - title: Aria Label
165
165
  blocks:
@@ -177,7 +177,7 @@
177
177
  flex: 0 0 auto
178
178
  properties:
179
179
  url: https://lowdefy.com
180
- icon: AiOutlineHome
180
+ icon: home
181
181
  ariaLabel: Go to home page
182
182
 
183
183
  - title: Rel Attribute
@@ -209,7 +209,7 @@
209
209
  properties:
210
210
  title: Go Back
211
211
  back: true
212
- icon: AiOutlineArrowLeft
212
+ icon: arrow-left
213
213
  - id: nav_home
214
214
  type: Anchor
215
215
  layout:
@@ -217,7 +217,7 @@
217
217
  properties:
218
218
  title: Go Home
219
219
  home: true
220
- icon: AiOutlineHome
220
+ icon: home
221
221
 
222
222
  - title: Keyboard Shortcuts
223
223
  blocks:
@@ -228,7 +228,7 @@
228
228
  properties:
229
229
  title: Documentation
230
230
  url: https://docs.lowdefy.com
231
- icon: AiOutlineBook
231
+ icon: Book
232
232
  events:
233
233
  onClick:
234
234
  shortcut: mod+shift+d
@@ -313,4 +313,4 @@
313
313
  properties:
314
314
  title: Large Red Link
315
315
  url: https://lowdefy.com
316
- icon: AiOutlineHeart
316
+ icon: heart
@@ -15,7 +15,7 @@
15
15
  */ export default {
16
16
  category: 'display',
17
17
  icons: [
18
- 'AiOutlineLoading3Quarters'
18
+ 'loading'
19
19
  ],
20
20
  valueType: null,
21
21
  cssKeys: {
@@ -65,7 +65,7 @@
65
65
  'string',
66
66
  'object'
67
67
  ],
68
- description: "Name of an React-Icon (See <a href='https://react-icons.github.io/react-icons/'>all icons</a>) or properties of an Icon block for anchor icon.",
68
+ description: 'Icon name (a semantic name like `edit`, a Lucide icon name like `Pencil`, or a set-qualified name like `tabler:Pencil`) or properties of an Icon block for anchor icon.',
69
69
  docs: {
70
70
  displayType: 'icon'
71
71
  }
@@ -76,10 +76,12 @@
76
76
  },
77
77
  href: {
78
78
  type: 'string',
79
+ urlKind: 'href',
79
80
  description: 'The href to link to when the anchor link is clicked.'
80
81
  },
81
82
  url: {
82
83
  type: 'string',
84
+ urlKind: 'url',
83
85
  description: 'External url to link to when the anchor link is clicked.'
84
86
  },
85
87
  rel: {
@@ -25,7 +25,7 @@ blocks:
25
25
  type: Anchor
26
26
  properties:
27
27
  title: With Icon
28
- icon: AiOutlineLink
28
+ icon: link
29
29
 
30
30
  - id: anchor_disabled
31
31
  type: Anchor
@@ -21,18 +21,18 @@
21
21
  - id: properties.icon string
22
22
  type: Anchor
23
23
  properties:
24
- icon: AiFillFire
24
+ icon: Flame
25
25
  - id: properties.icon object
26
26
  type: Anchor
27
27
  properties:
28
28
  title: Click here
29
29
  icon:
30
30
  color: red
31
- name: AiFillRocket
31
+ name: Rocket
32
32
  - id: properties.icon and properties.title
33
33
  type: Anchor
34
34
  properties:
35
- icon: AiOutlineLink
35
+ icon: link
36
36
  title: This is the anchor title
37
37
  - id: properties.disabled
38
38
  type: Anchor
@@ -42,7 +42,7 @@
42
42
  - id: properties.icon, properties.title and properties.disabled
43
43
  type: Anchor
44
44
  properties:
45
- icon: AiOutlineLink
45
+ icon: link
46
46
  title: This is the anchor title
47
47
  disabled: true
48
48
  - id: properties.url
@@ -92,7 +92,7 @@
92
92
  type: Anchor
93
93
  properties:
94
94
  title: Click here
95
- icon: AiOutlineLink
95
+ icon: link
96
96
  style:
97
97
  color: green !important
98
98
  fontSize: 8
@@ -103,7 +103,7 @@
103
103
  loading: true
104
104
  properties:
105
105
  title: Click here
106
- icon: AiOutlineLink
106
+ icon: link
107
107
  style:
108
108
  color: green !important
109
109
  fontSize: 8
@@ -896,7 +896,7 @@
896
896
  layout:
897
897
  flex: 0 0 auto
898
898
  properties:
899
- name: AiOutlineRocket
899
+ name: Rocket
900
900
  size: 32
901
901
  color: '#1677ff'
902
902
  - id: box_feature_a_title
@@ -918,7 +918,7 @@
918
918
  layout:
919
919
  flex: 0 0 auto
920
920
  properties:
921
- name: AiOutlineSafety
921
+ name: Shield
922
922
  size: 32
923
923
  color: '#52c41a'
924
924
  - id: box_feature_b_title
@@ -940,7 +940,7 @@
940
940
  layout:
941
941
  flex: 0 0 auto
942
942
  properties:
943
- name: AiOutlineApi
943
+ name: Plug
944
944
  size: 32
945
945
  color: '#722ed1'
946
946
  - id: box_feature_c_title
@@ -1110,7 +1110,7 @@
1110
1110
  layout:
1111
1111
  flex: 0 0 auto
1112
1112
  properties:
1113
- name: AiOutlineCheckCircle
1113
+ name: check-circle
1114
1114
  size: 20
1115
1115
  color: '#52c41a'
1116
1116
  - id: box_inbox_item_1_body
@@ -1147,7 +1147,7 @@
1147
1147
  layout:
1148
1148
  flex: 0 0 auto
1149
1149
  properties:
1150
- name: AiOutlineUserAdd
1150
+ name: UserPlus
1151
1151
  size: 20
1152
1152
  color: '#1677ff'
1153
1153
  - id: box_inbox_item_2_body
@@ -1184,7 +1184,7 @@
1184
1184
  layout:
1185
1185
  flex: 0 0 auto
1186
1186
  properties:
1187
- name: AiOutlineWarning
1187
+ name: warning
1188
1188
  size: 20
1189
1189
  color: '#faad14'
1190
1190
  - id: box_inbox_item_3_body
@@ -1247,7 +1247,7 @@
1247
1247
  layout:
1248
1248
  flex: 0 0 auto
1249
1249
  properties:
1250
- name: AiOutlineDashboard
1250
+ name: Gauge
1251
1251
  size: 16
1252
1252
  color: '#1677ff'
1253
1253
  - id: box_sidebar_text_dashboard
@@ -1274,7 +1274,7 @@
1274
1274
  layout:
1275
1275
  flex: 0 0 auto
1276
1276
  properties:
1277
- name: AiOutlineProject
1277
+ name: SquareKanban
1278
1278
  size: 16
1279
1279
  color: rgba(128, 128, 128, 0.7)
1280
1280
  - id: box_sidebar_text_projects
@@ -1301,7 +1301,7 @@
1301
1301
  layout:
1302
1302
  flex: 0 0 auto
1303
1303
  properties:
1304
- name: AiOutlineSetting
1304
+ name: settings
1305
1305
  size: 16
1306
1306
  color: rgba(128, 128, 128, 0.7)
1307
1307
  - id: box_sidebar_text_settings
@@ -14,32 +14,14 @@
14
14
  limitations under the License.
15
15
  */ import React from 'react';
16
16
  import { withBlockDefaults, HtmlComponent } from '@lowdefy/block-utils';
17
- // dataset keys are camelCase (data-record-id → recordId); config authors
18
- // write the attributes in kebab-case, so hand them back as snake_case.
19
- function toSnakeCase(key) {
20
- return key.replace(/[A-Z]/g, (match)=>`_${match.toLowerCase()}`);
21
- }
22
- const ClickableHtml = ({ blockId, classNames, events, properties, methods, styles })=>{
23
- // Each clickable element names the event it fires in its data-event
24
- // attribute (data-event="onEditClick" → events.onEditClick), so every
25
- // target in the markup has its own action chain. Its other data-*
26
- // attributes are the event object.
27
- function onClick(clickEvent) {
28
- const target = clickEvent.target.closest('[data-event]');
29
- if (!target || !clickEvent.currentTarget.contains(target)) return;
30
- const { event: name, ...data } = target.dataset;
31
- if (!name) return;
32
- clickEvent.preventDefault();
33
- const event = {};
34
- Object.keys(data).forEach((key)=>{
35
- event[toSnakeCase(key)] = data[key];
36
- });
37
- methods.triggerEvent({
38
- name,
39
- event
40
- });
41
- }
42
- return /*#__PURE__*/ React.createElement(HtmlComponent, {
17
+ // Each clickable element names the event it fires in its data-event attribute
18
+ // (data-event="onEditClick" → events.onEditClick), so every target in the
19
+ // markup has its own action chain. Its other data-* attributes are the event
20
+ // object. HtmlComponent finds the target, including inside data-popover
21
+ // content, and prevents the element's default action. Only the events listed
22
+ // in properties.dataEvents fire, since the markup can hold data.
23
+ const ClickableHtml = ({ blockId, classNames, events, properties, methods, styles })=>/*#__PURE__*/ React.createElement(HtmlComponent, {
24
+ dataEvents: properties.dataEvents,
43
25
  div: true,
44
26
  events: events,
45
27
  html: properties.html,
@@ -47,7 +29,6 @@ const ClickableHtml = ({ blockId, classNames, events, properties, methods, style
47
29
  methods: methods,
48
30
  className: classNames?.element,
49
31
  style: styles?.element,
50
- onClick: onClick
32
+ onDataEvent: methods.triggerEvent
51
33
  });
52
- };
53
34
  export default withBlockDefaults(ClickableHtml);
@@ -16,6 +16,9 @@
16
16
  - id: buttons_basic
17
17
  type: ClickableHtml
18
18
  properties:
19
+ dataEvents:
20
+ - onSmallClick
21
+ - onLargeClick
19
22
  html: '<p>Pick a size: <button data-event="onSmallClick">Small</button> <button data-event="onLargeClick">Large</button></p>'
20
23
  events:
21
24
  onSmallClick:
@@ -44,6 +47,8 @@
44
47
  - id: list_rows
45
48
  type: ClickableHtml
46
49
  properties:
50
+ dataEvents:
51
+ - onRowClick
47
52
  html: '<ul style="list-style: none; padding: 0; margin: 0;"><li data-event="onRowClick" data-record-id="rec_1" style="padding: 8px; cursor: pointer; border-bottom: 1px solid var(--ant-color-border);">First record</li><li data-event="onRowClick" data-record-id="rec_2" style="padding: 8px; cursor: pointer; border-bottom: 1px solid var(--ant-color-border);">Second record</li><li data-event="onRowClick" data-record-id="rec_3" style="padding: 8px; cursor: pointer;">Third record</li></ul>'
48
53
  events:
49
54
  onRowClick:
@@ -69,6 +74,8 @@
69
74
  - id: mixed_content
70
75
  type: ClickableHtml
71
76
  properties:
77
+ dataEvents:
78
+ - onCommentClick
72
79
  html: '<p>This <a href="https://lowdefy.com" target="_blank">link</a> navigates normally, but <a href="#" data-event="onCommentClick" data-thread-id="t_9">this one</a> fires onCommentClick instead.</p>'
73
80
  events:
74
81
  onCommentClick:
@@ -99,6 +106,9 @@
99
106
  border: 1px solid var(--ant-color-border)
100
107
  background: var(--ant-color-bg-container)
101
108
  properties:
109
+ dataEvents:
110
+ - onEditClick
111
+ - onRemoveClick
102
112
  html: '<h4 style="margin: 0 0 8px 0;">Card</h4><p style="margin: 0 0 8px 0; color: var(--ant-color-text-secondary);">Yours to change or remove until tomorrow.</p><button data-event="onEditClick">Edit</button> <button data-event="onRemoveClick">Remove</button>'
103
113
  events:
104
114
  onEditClick:
@@ -111,3 +121,79 @@
111
121
  type: SetState
112
122
  params:
113
123
  style_card_action: remove
124
+
125
+ - title: Clickable icons and a popover menu
126
+ blocks:
127
+ - id: row_actions
128
+ type: ClickableHtml
129
+ properties:
130
+ dataEvents:
131
+ - onEdit
132
+ - onDuplicate
133
+ - name: onDelete
134
+ confirm: Delete invoice INV-042?
135
+ html: '<p>Invoice INV-042 <i data-icon="edit" data-event="onEdit" data-id="42" data-tooltip="Edit" style="cursor: pointer"></i> <span data-popover="more" style="cursor: pointer"><i data-icon="more-vertical"></i></span></p><div data-popover-content="more" hidden><p data-event="onDuplicate" data-id="42" style="cursor: pointer; margin: 0 0 8px"><i data-icon="copy"></i> Duplicate</p><p data-event="onDelete" data-id="42" style="cursor: pointer; margin: 0; color: var(--ant-color-error)"><i data-icon="delete"></i> Delete</p></div>'
136
+ events:
137
+ onEdit:
138
+ - id: set_edit
139
+ type: SetState
140
+ params:
141
+ row_actions_last: { _string.concat: ['edit ', { _event: id }] }
142
+ onDuplicate:
143
+ - id: set_duplicate
144
+ type: SetState
145
+ params:
146
+ row_actions_last: { _string.concat: ['duplicate ', { _event: id }] }
147
+ onDelete:
148
+ - id: set_delete
149
+ type: SetState
150
+ params:
151
+ row_actions_last: { _string.concat: ['delete ', { _event: id }] }
152
+ - id: row_actions_result
153
+ type: Html
154
+ properties:
155
+ html:
156
+ _string.concat:
157
+ - '<p>Last action: <code>'
158
+ - _state:
159
+ key: row_actions_last
160
+ default: 'none yet'
161
+ - '</code></p>'
162
+
163
+ - title: Confirm before an event
164
+ blocks:
165
+ - id: confirm_actions
166
+ type: ClickableHtml
167
+ properties:
168
+ dataEvents:
169
+ - name: onDelete
170
+ confirm: true
171
+ - onArchive
172
+ html: '<p>INV-2026-0042 <i data-icon="delete" data-event="onDelete" data-id="42" data-tooltip="Delete" data-confirm="Delete invoice INV-2026-0042?" style="cursor: pointer; color: var(--ant-color-error)"></i> <span data-event="onArchive" data-id="42" data-confirm style="cursor: pointer; color: var(--ant-color-primary)">Archive</span></p>'
173
+ events:
174
+ onDelete:
175
+ - id: deleted
176
+ type: SetState
177
+ params:
178
+ confirm_last:
179
+ _string.concat:
180
+ - 'deleted '
181
+ - _event: id
182
+ onArchive:
183
+ - id: archived
184
+ type: SetState
185
+ params:
186
+ confirm_last:
187
+ _string.concat:
188
+ - 'archived '
189
+ - _event: id
190
+ - id: confirm_result
191
+ type: Html
192
+ properties:
193
+ html:
194
+ _string.concat:
195
+ - '<p>Last action: <code>'
196
+ - _state:
197
+ key: confirm_last
198
+ default: 'none yet'
199
+ - '</code></p>'
@@ -19,8 +19,26 @@
19
19
  cssKeys: {
20
20
  element: 'The Html element.'
21
21
  },
22
+ hazards: [
23
+ {
24
+ id: 'html-style-stripped',
25
+ message: 'Content is sanitised with DOMPurify, so <style>, <script> and inline event handlers are removed before render. Clicks are wired through data-event attributes instead of inline handlers.',
26
+ see: 'display-blocks/clickablehtml'
27
+ },
28
+ {
29
+ id: 'clickable-html-data-events',
30
+ message: 'List every event the HTML fires in properties.dataEvents: a data-event whose name is not listed does nothing. HTML built from user or request data must escape that data, so the data cannot add data-event elements of its own: _nunjucks escapes {{ values }} unless they are marked safe, while _string.concat and _js do not escape.',
31
+ see: 'display-blocks/clickablehtml'
32
+ },
33
+ {
34
+ id: 'clickable-html-confirm-destructive',
35
+ message: 'Give an event that deletes or changes data confirm in dataEvents ({ name: onDelete, confirm: "Delete this row?" }), so every click on it asks first and only OK fires it. data-confirm="Delete this row?" on the element asks too, but only where the markup says so.',
36
+ see: 'concepts/html-attributes'
37
+ }
38
+ ],
22
39
  // Each clickable element names its event in a data-event attribute, so the
23
40
  // event names this block fires are authored in its html.
41
+ dynamicEvents: true,
24
42
  events: {
25
43
  onTextSelection: 'Trigger action when text is selected and pass selected text to the event object.'
26
44
  },
@@ -28,9 +46,47 @@
28
46
  type: 'object',
29
47
  additionalProperties: false,
30
48
  properties: {
49
+ dataEvents: {
50
+ type: 'array',
51
+ description: 'The events the HTML may fire. A data-event whose name is not listed does nothing, and a click on it logs a console warning; with no dataEvents the HTML fires no events. List an event by name, or as { name, confirm } to make every click on it ask first.',
52
+ items: {
53
+ oneOf: [
54
+ {
55
+ type: 'string',
56
+ description: 'An event name, as written in data-event.'
57
+ },
58
+ {
59
+ type: 'object',
60
+ additionalProperties: false,
61
+ required: [
62
+ 'name'
63
+ ],
64
+ properties: {
65
+ name: {
66
+ type: 'string',
67
+ description: 'An event name, as written in data-event.'
68
+ },
69
+ confirm: {
70
+ oneOf: [
71
+ {
72
+ type: 'boolean',
73
+ description: 'Ask before the event fires, whatever the HTML says, with the element\'s data-confirm message or "Are you sure?".'
74
+ },
75
+ {
76
+ type: 'string',
77
+ minLength: 1,
78
+ description: 'Ask before the event fires, whatever the HTML says, with this message.'
79
+ }
80
+ ]
81
+ }
82
+ }
83
+ }
84
+ ]
85
+ }
86
+ },
31
87
  html: {
32
88
  type: 'string',
33
- description: 'Content to be rendered as Html. An element with a data-event attribute fires the event it names when clicked (data-event="onEditClick" fires events.onEditClick), and its default browser action is prevented. The event object holds the element\'s other data-* attributes with snake_case keys, so data-event="onEditClick" data-record-id="42" gives { record_id: "42" }.',
89
+ description: 'Content to be rendered as Html. An element with a data-event attribute fires the event it names when clicked (data-event="onEditClick" fires events.onEditClick), if dataEvents lists it, and its default browser action is prevented. The event object holds the element\'s other data-* attributes with snake_case keys, so data-event="onEditClick" data-record-id="42" gives { record_id: "42" }. Targets that are not links or buttons become keyboard focusable, and Enter or Space clicks them. A data-event inside popover content fires too, then closes the popover. A link with data-event fires the event and does not navigate. data-confirm="Delete this row?" on a data-event element asks first: only OK fires the event (bare data-confirm asks "Are you sure?"). Escape user and request data in the HTML, so it cannot add data-event elements of its own. All Html block attributes work too: data-icon, data-tooltip, data-popover, data-page-id links, data-new-tab, data-tag, data-status, data-time, data-format, data-avatar, data-copy, data-truncate and data-tone. See the HTML attributes docs page.',
34
90
  docs: {
35
91
  displayType: 'text-area'
36
92
  }
@@ -18,6 +18,9 @@ blocks:
18
18
  - id: clickable_basic
19
19
  type: ClickableHtml
20
20
  properties:
21
+ dataEvents:
22
+ - onGreetClick
23
+ - onWaveClick
21
24
  html: '<p>Hello <button data-event="onGreetClick" data-user-id="u_1">World</button> <button data-event="onWaveClick" data-user-id="u_2">Wave</button></p>'
22
25
  events:
23
26
  onGreetClick:
@@ -67,3 +70,119 @@ blocks:
67
70
  type: ClickableHtml
68
71
  properties:
69
72
  html: <p>Safe content</p><script>alert('xss')</script>
73
+
74
+ - id: clickable_confirm
75
+ type: ClickableHtml
76
+ properties:
77
+ dataEvents:
78
+ - onDelete
79
+ html: '<button id="confirm_delete" data-event="onDelete" data-row-id="7" data-confirm="Delete row 7?">Delete</button> <button id="proto_event" data-event="__proto__">Proto</button>'
80
+ events:
81
+ onDelete:
82
+ - id: count_delete
83
+ type: SetState
84
+ params:
85
+ delete_count:
86
+ _sum:
87
+ - _state:
88
+ key: delete_count
89
+ default: 0
90
+ - 1
91
+
92
+ - id: clickable_confirm_result
93
+ type: Html
94
+ properties:
95
+ html:
96
+ _string.concat:
97
+ - '<span id="delete_count">'
98
+ - _json.stringify:
99
+ - _state:
100
+ key: delete_count
101
+ default: 0
102
+ - '</span>'
103
+
104
+ - id: clickable_allowlist
105
+ type: ClickableHtml
106
+ properties:
107
+ dataEvents:
108
+ - onListedClick
109
+ html: '<span id="listed_target" data-event="onListedClick">Listed</span> <span id="unlisted_target" data-event="onUnlistedClick">Unlisted</span>'
110
+ events:
111
+ onListedClick:
112
+ - id: set_listed
113
+ type: SetState
114
+ params:
115
+ allowlist_fired: listed
116
+ onUnlistedClick:
117
+ - id: set_unlisted
118
+ type: SetState
119
+ params:
120
+ allowlist_fired: unlisted
121
+
122
+ - id: clickable_declared_confirm
123
+ type: ClickableHtml
124
+ properties:
125
+ dataEvents:
126
+ - name: onRemove
127
+ confirm: Remove row 3?
128
+ html: '<button id="declared_remove" data-event="onRemove" data-row-id="3">Remove</button>'
129
+ events:
130
+ onRemove:
131
+ - id: set_removed
132
+ type: SetState
133
+ params:
134
+ removed_row:
135
+ _event: row_id
136
+
137
+ - id: clickable_refresh
138
+ type: ClickableHtml
139
+ properties:
140
+ dataEvents:
141
+ - onRefreshSoon
142
+ - onRefreshDelete
143
+ html:
144
+ _string.concat:
145
+ - '<button id="refresh_soon" data-event="onRefreshSoon">Refresh soon</button><p id="refresh_count">Refreshed '
146
+ - _state:
147
+ key: refresh_count
148
+ default: 0
149
+ - '</p><button id="refresh_delete" data-event="onRefreshDelete" data-id="5" data-confirm="Delete 5?">Delete</button> <span id="refresh_more" data-popover="more">More</span><div data-popover-content="more" hidden><span class="refresh-menu">Menu after '
150
+ - _state:
151
+ key: refresh_count
152
+ default: 0
153
+ - '</span></div>'
154
+ events:
155
+ onRefreshSoon:
156
+ - id: wait
157
+ type: Wait
158
+ params:
159
+ ms: 1000
160
+ - id: refresh
161
+ type: SetState
162
+ params:
163
+ refresh_count: 1
164
+ onRefreshDelete:
165
+ - id: set_refresh_deleted
166
+ type: SetState
167
+ params:
168
+ refresh_deleted:
169
+ _event: id
170
+
171
+ - id: clickable_events_result
172
+ type: Html
173
+ properties:
174
+ html:
175
+ _string.concat:
176
+ - '<span id="allowlist_fired">'
177
+ - _state:
178
+ key: allowlist_fired
179
+ default: ''
180
+ - '</span><span id="removed_row">'
181
+ - _state:
182
+ key: removed_row
183
+ default: ''
184
+ - '</span><span id="refresh_deleted">'
185
+ - _state:
186
+ key: refresh_deleted
187
+ default: ''
188
+ - '</span>'