alchemy-form 0.3.0-alpha.3 → 0.3.0-alpha.5

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/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## 0.3.0-alpha.5 (2025-07-10)
2
+
3
+ * Add `al-datetime-input` to properly handle Date values with timezones
4
+
5
+ ## 0.3.0-alpha.4 (2025-07-10)
6
+
7
+ * Always make `al-field`'s `getFieldType()` method return a string
8
+ * Add the `mixed` field view
9
+ * Just clear the al-table when an falsy fieldset is assigned
10
+ * Explicitly pass on the `self` value in alchemy_select_item
11
+ * Add more info to enum badges
12
+ * Improve array-field buttons
13
+
1
14
  ## 0.3.0-alpha.3 (2024-08-04)
2
15
 
3
16
  * Add `original_value_container` property to `<al-field>` elements, for when they're not inside a `<al-form>` element but still need the original container
@@ -0,0 +1,6 @@
1
+ al-datetime-input {
2
+ > * {
3
+ width: 100%;
4
+ height: 100%;
5
+ }
6
+ }
@@ -5,13 +5,20 @@ al-field-array {
5
5
  al-field-array-entry {
6
6
  display: flex;
7
7
 
8
- > .button {
8
+ > .button-remove-wrapper {
9
9
  display: flex;
10
10
  align-content: center;
11
- padding-left: 0.5rem;
11
+ padding-left: 0.75rem;
12
+
13
+ > .remove {
14
+ height: 100%;
15
+ display: flex;
16
+ flex-flow: column;
17
+ gap: 0.5em;
18
+ }
12
19
  }
13
20
 
14
- .button .remove > * {
21
+ .button-remove-wrapper .remove > * {
15
22
  writing-mode: vertical-rl;
16
23
  }
17
24
  }
File without changes
@@ -2,18 +2,38 @@
2
2
  @use "styleboost/inputs";
3
3
 
4
4
  @layer defaults {
5
+ $accent: styleboost.themePropertyVar('color', 'accent', 'table');
6
+ $accent_rgb: styleboost.themePropertyVar('color', 'accent-rgb', 'table');
7
+
5
8
  al-table {
9
+ // Define custom properties for al-table
10
+ --al-table-color-header-bg: var(--color-t-current-bg-subtle, var(--color-t-primary-bg-subtle));
11
+ --al-table-color-header-fg: var(--color-t-current-bg-subtle-text, var(--color-t-primary-bg-subtle-text));
12
+ --al-table-color-footer-bg: var(--color-t-current-bg-subtle, var(--color-t-primary-bg-subtle));
13
+ --al-table-color-footer-fg: var(--color-t-current-bg-subtle-text, var(--color-t-primary-bg-subtle-text));
14
+ --al-table-color-border: var(--color-t-current-bg-subtle, var(--color-t-primary-bg-subtle));
15
+ --al-table-color-selected-bg: var(--color-t-current-bg-soft, var(--color-t-primary-bg-soft));
16
+ --al-table-color-selected-fg: var(--color-t-current-bg-soft-text, var(--color-t-primary-bg-soft-text));
17
+
6
18
  display: flex;
7
19
  flex-flow: column;
20
+ border-radius: var(--size-p-table-border-radius);
21
+ border-width: var(--size-p-table-border);
22
+ border-style: var(--style-p-table-border);
23
+ border-color: var(--al-table-color-border);
24
+ background-color: var(--color-p-table-bg);
25
+ overflow: hidden;
8
26
 
9
27
  .aft-content {
10
- overflow-x: scroll;
28
+ overflow-x: auto;
11
29
  scrollbar-width: thin;
12
30
  }
13
31
 
14
32
  table {
15
33
  @extend .table;
16
34
  width: 100%;
35
+ border: none;
36
+ border-radius: 0;
17
37
  }
18
38
 
19
39
  &.table-hover {
@@ -29,27 +49,59 @@
29
49
  }
30
50
 
31
51
  &.table-bordered {
32
- // Custom bordering
52
+ table {
53
+ @extend .table-bordered;
54
+ }
33
55
  }
34
56
 
35
57
  thead {
36
-
37
58
  td,
38
59
  th {
60
+ background-color: var(--al-table-color-header-bg);
61
+ color: var(--al-table-color-header-fg);
62
+ text-transform: uppercase;
63
+ font-weight: 500;
64
+ font-size: 0.9rem;
65
+ border-bottom-color: var(--al-table-color-border);
66
+
67
+ al-icon {
68
+ margin-left: 0.5rem;
69
+ vertical-align: middle;
70
+ }
71
+
39
72
  &.sortable {
40
73
  cursor: pointer;
74
+ user-select: none;
75
+
76
+ &:hover {
77
+ opacity: 0.8;
78
+ }
41
79
  }
42
80
 
43
81
  a.sorting-anchor {
44
82
  text-decoration: none;
45
83
  color: inherit;
84
+ display: block;
46
85
  }
47
86
  }
87
+
88
+ th input {
89
+ @extend .input-defaults;
90
+ width: 100%;
91
+ height: 2rem;
92
+ font-size: 0.875rem;
93
+ padding: 0.25rem 0.5rem;
94
+ }
48
95
  }
49
96
 
50
- th input {
51
- width: 100%;
52
- height: 2rem;
97
+ tbody {
98
+ tr.aft-selected {
99
+ td,
100
+ th {
101
+ --color-s-table-bg: var(--al-table-color-selected-bg);
102
+ --color-s-table-bg-text: var(--al-table-color-selected-fg);
103
+ }
104
+ }
53
105
  }
54
106
 
55
107
  td al-field[field-type="fixed_decimal"] {
@@ -57,7 +109,10 @@
57
109
  }
58
110
 
59
111
  footer {
112
+ background-color: var(--al-table-color-footer-bg);
113
+ color: var(--al-table-color-footer-fg);
60
114
  padding: 0.5rem 1rem;
115
+ border-top: var(--size-p-table-border-inner) var(--style-p-table-border) var(--al-table-color-border);
61
116
 
62
117
  &:empty {
63
118
  display: none;
File without changes
@@ -17,4 +17,4 @@
17
17
  @use "_virtual_scroll.scss";
18
18
  @use "_settings_editor.scss";
19
19
  @use "_enum_badge.scss";
20
- @use "_dropdown.scss";
20
+ @use "_datetime.scss";
File without changes
@@ -0,0 +1,127 @@
1
+ /**
2
+ * The al-datetime-input:
3
+ * Populate an input on the browser-side with correct timezone info
4
+ *
5
+ * @author Jelle De Loecker <jelle@elevenways.be>
6
+ * @since 0.3.0
7
+ * @version 0.3.0
8
+ */
9
+ const DatetimeInput = Function.inherits('Alchemy.Element.Form.Base', 'DatetimeInput');
10
+
11
+ /**
12
+ * Get/set the mode
13
+ *
14
+ * @author Jelle De Loecker <jelle@elevenways.be>
15
+ * @since 0.3.0
16
+ * @version 0.3.0
17
+ */
18
+ DatetimeInput.setAttribute('datemode', null, function setMode(datemode) {
19
+ this.populateInputWithValue(this.value, datemode);
20
+ return datemode;
21
+ });
22
+
23
+ /**
24
+ * Get/set the value
25
+ *
26
+ * @author Jelle De Loecker <jelle@elevenways.be>
27
+ * @since 0.3.0
28
+ * @version 0.3.0
29
+ */
30
+ DatetimeInput.setAttribute('value', null, function setValue(value) {
31
+ return this.populateInputWithValue(value, this.datemode);
32
+ });
33
+
34
+ /**
35
+ * Set the value with a function call
36
+ *
37
+ * @author Jelle De Loecker <jelle@elevenways.be>
38
+ * @since 0.3.0
39
+ * @version 0.3.0
40
+ */
41
+ DatetimeInput.setMethod(function setValue(value) {
42
+ this.value = value;
43
+ });
44
+
45
+ /**
46
+ * Revalidate the value
47
+ *
48
+ * @author Jelle De Loecker <jelle@elevenways.be>
49
+ * @since 0.3.0
50
+ * @version 0.3.0
51
+ *
52
+ * @return {Object[]}
53
+ */
54
+ DatetimeInput.setMethod(function populateInput() {
55
+ return this.populateInputWithValue(this.value, this.datemode);
56
+ });
57
+
58
+ /**
59
+ * Revalidate the value
60
+ *
61
+ * @author Jelle De Loecker <jelle@elevenways.be>
62
+ * @since 0.3.0
63
+ * @version 0.3.0
64
+ *
65
+ * @return {Object[]}
66
+ */
67
+ DatetimeInput.setMethod(function populateInputWithValue(value, datemode) {
68
+
69
+ let iso_date,
70
+ date;
71
+
72
+ if (value) {
73
+ date = Date.create(value);
74
+ iso_date = date.toISOString();
75
+ } else {
76
+ iso_date = '';
77
+ }
78
+
79
+ value = iso_date;
80
+
81
+ if (Blast.isServer) {
82
+ return value;
83
+ }
84
+
85
+ if (arguments.length == 1) {
86
+ datemode = this.datemode;
87
+ }
88
+
89
+ let input = this.querySelector('input');
90
+
91
+ if (!datemode) {
92
+ datemode = 'datetime';
93
+ }
94
+
95
+ if (!input) {
96
+ input = this.createElement('input');
97
+ input.setAttribute('type', datemode + '-local');
98
+ }
99
+
100
+ if (!value) {
101
+ input.value = '';
102
+ return '';
103
+ }
104
+
105
+ let formatted;
106
+
107
+ if (datemode == 'date') {
108
+ formatted = date.format('Y-m-d');
109
+ } else {
110
+ formatted = date.format('Y-m-d\\TH:i:s');
111
+ }
112
+
113
+ input.value = formatted;
114
+
115
+ return iso_date;
116
+ });
117
+
118
+ /**
119
+ * Added to the DOM
120
+ *
121
+ * @author Jelle De Loecker <jelle@elevenways.be>
122
+ * @since 0.3.0
123
+ * @version 0.3.0
124
+ */
125
+ DatetimeInput.setMethod(function introduced() {
126
+ this.populateInput();
127
+ });
@@ -880,7 +880,7 @@ Field.setMethod(function getFieldType() {
880
880
  }
881
881
  }
882
882
 
883
- return result;
883
+ return result || '';
884
884
  });
885
885
 
886
886
  /**
@@ -932,6 +932,10 @@ Table.setMethod(function onFieldsetAssignment(value, old_value) {
932
932
 
933
933
  this.clearAll();
934
934
 
935
+ if (!value) {
936
+ return;
937
+ }
938
+
935
939
  if (!(value instanceof Classes.Alchemy.Criteria.FieldSet)) {
936
940
  if (Array.isArray(value)) {
937
941
  value = Classes.Alchemy.Criteria.FieldSet.fromArray(value);
@@ -281,7 +281,8 @@ VirtualScroll.setMethod(function ensureTriggerElements() {
281
281
  }
282
282
  }
283
283
  }, {
284
- threshold: 0,
284
+ threshold: 0.1,
285
+ root: this,
285
286
  rootMargin: '50px 0px 50px 0px',
286
287
  });
287
288
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "alchemy-form",
3
3
  "description": "Form plugin for Alchemy",
4
- "version": "0.3.0-alpha.3",
4
+ "version": "0.3.0-alpha.5",
5
5
  "repository": {
6
6
  "type" : "git",
7
7
  "url" : "https://github.com/11ways/alchemy-form.git"
@@ -13,7 +13,8 @@
13
13
  }
14
14
  %>
15
15
  {% else %}
16
- <button class="add-entry">
16
+ <button class="button add-entry">
17
+ <al-icon icon-name="plus"></al-icon>
17
18
  {%t "add-entry" name=alchemy_field.field_name title=alchemy_field.field_title %}
18
19
  </button>
19
20
  {% /if %}
@@ -14,8 +14,9 @@
14
14
  {% if self.alchemy_field_array.max_entry_count eq 1 %}
15
15
 
16
16
  {% else %}
17
- <div class="button">
18
- <button class="remove">
17
+ <div class="button-remove-wrapper">
18
+ <button class="button remove">
19
+ <al-icon icon-name="trash"></al-icon>
19
20
  {%t "remove-entry" name=alchemy_field.field_name title=alchemy_field.field_title %}
20
21
  </button>
21
22
  </div>
@@ -1,5 +1,5 @@
1
1
  {% if self.custom_template %}
2
- {% include self.custom_template %}
2
+ {% include self.custom_template self=self %}
3
3
  {% else %}
4
4
  {{ self.display_title }}
5
5
  {% /if %}
@@ -1,13 +1,13 @@
1
- <%
2
- if (value) {
3
- value = value.format('Y-m-d');
4
- }
5
- %>
6
- <input
7
- value=<% value %>
8
- class="alchemy-field-value"
9
- type="date"
10
- form=<% form_id %>
11
- name=<% path %>
12
- pattern="\d{4}-\d{2}-\d{2}"
13
- >
1
+ <al-datetime-input
2
+ datemode="date"
3
+ >
4
+ <% $0.setValue(value) %>
5
+ <input
6
+ value=<% value %>
7
+ class="alchemy-field-value"
8
+ type="date"
9
+ form=<% form_id %>
10
+ name=<% path %>
11
+ pattern="\d{4}-\d{2}-\d{2}"
12
+ >
13
+ </al-datetime-input>
@@ -1,20 +1,13 @@
1
- <%
2
-
3
- if (value) {
4
-
5
- // Make sure it's a date
6
- value = Date.create(value);
7
-
8
- // According to MDN `toISOString()` should work,
9
- // but neither Chrome or Firefox allow that format (it still contains timezone info)
10
- value = value.format('Y-m-d\\TH:i:s');
11
- }
12
- %>
13
- <input
14
- value=<% value %>
15
- class="alchemy-field-value"
16
- type="datetime-local"
17
- form=<% form_id %>
18
- name=<% path %>
19
- pattern="\d{4}-\d{2}-\d{2} \d{1,2}:\d{1,2}(?::\d{1,2})?"
20
- >
1
+ <al-datetime-input
2
+ datemode="datetime"
3
+ >
4
+ <% $0.setValue(value) %>
5
+ <input
6
+ class="alchemy-field-value"
7
+ type="datetime-local"
8
+ form=<% form_id %>
9
+ name=<% path %>
10
+ pattern="\d{4}-\d{2}-\d{2} \d{1,2}:\d{1,2}(?::\d{1,2})?"
11
+ value=""
12
+ >
13
+ </al-datetime-input>
@@ -0,0 +1,9 @@
1
+ <al-code-input
2
+ class="alchemy-field-value"
3
+ form=<% form_id %>
4
+ name=<% path %>
5
+ placeholder={% alchemy_field.placeholder %}
6
+ language-mode="json"
7
+ value-is-object
8
+ #value={% value %}
9
+ ></al-code-input>
@@ -5,8 +5,8 @@
5
5
  </span>
6
6
  </span>
7
7
  {% else %}
8
- {% set enum_config to self.config.getValueConfiguration(value) %}
9
- {% set display_value to OR enum_config.title OR enum_config.name OR value %}
8
+ {% set enum_config to field_context.config.getValueConfiguration(value) %}
9
+ {% set display_value to enum_config.short_title OR enum_config.title OR enum_config.name OR value %}
10
10
 
11
11
  <span class="badge alchemy-field-value alchemy-field-enum">
12
12
  <% $0.classList.add('enum-' + value) %>
@@ -16,15 +16,19 @@
16
16
  {% /if %}
17
17
 
18
18
  {% if enum_config.color %}
19
- <% $0.style.setProperty('--badge-bg', enum_config.color) %>
19
+ <% $0.style.setProperty('--color-p-badge-bg', enum_config.color) %>
20
20
  {% /if %}
21
21
 
22
22
  {% if enum_config.text_color %}
23
- <% $0.style.setProperty('--badge-color', enum_config.text_color) %>
23
+ <% $0.style.setProperty('--color-p-badge-bg-text', enum_config.text_color) %>
24
24
  {% /if %}
25
25
 
26
26
  {% if enum_config.icon %}
27
- <al-icon class="value-icon" icon-name={% enum_config.icon %}></al-icon>
27
+ <al-icon
28
+ class="value-icon"
29
+ icon-name={% enum_config.icon %}
30
+ icon-style={% enum_config.icon_tyle %}
31
+ ></al-icon>
28
32
  {% /if %}
29
33
 
30
34
  <span class="alchemy-enum-display-value">{{ display_value }}</span>
@@ -1,93 +0,0 @@
1
- @use "styleboost";
2
- @use "styleboost/inputs";
3
- @use "styleboost/utilities/properties";
4
-
5
- @layer defaults {
6
-
7
- :root {
8
- --size-c-dropdown-border: 0px;
9
- --style-c-dropdown-border: solid;
10
- --size-c-dropdown-border-radius: 4px;
11
- --color-c-dropdown-bg: white;
12
- }
13
-
14
- al-dropdown {
15
- // Only extend the input defaults (custom properties),
16
- // that way we don't inherit the actual applied values to padding etc
17
- @extend .input-defaults;
18
-
19
- --color-p-dropdown-bg: #{properties.backgroundColor('dropdown')};
20
-
21
- --color-p-dropdown-active-item-bg: var(--color-p-input-accent);
22
- --color-p-dropdown-active-item-bg-text: var(--color-p-input-accent-text);
23
-
24
- --color-p-dropdown-selected-item-bg: var(--color-p-input-accent);
25
- --color-p-dropdown-selected-item-bg-text: var(--color-p-input-accent-text);
26
-
27
- --size-p-dropdown-border-radius: var(--size-c-dropdown-border-radius);
28
-
29
- display: block;
30
- position: relative;
31
-
32
- .dropdown-trigger-wrapper > button {
33
- @extend .button;
34
- }
35
-
36
- .dropdown-items-wrapper {
37
- position: fixed;
38
- box-shadow: 0 12px 28px #0003,0 2px 4px #0000001a,inset 0 0 0 1px #ffffff80;
39
- border-radius: var(--size-p-dropdown-border-radius);
40
- background-color: var(--color-p-dropdown-bg);
41
-
42
- [slot="dropdown-items"] {
43
- // display: flex;
44
- // flex-flow: column;
45
- display: grid;
46
- grid-template-columns: max-content 1fr;
47
- grid-auto-rows: auto;
48
- grid-template-areas: "icons titles";
49
- gap: 0px 1rem;
50
-
51
- al-dropdown-item {
52
- display: grid;
53
- grid-template-columns: subgrid;
54
- grid-template-rows: subgrid;
55
- grid-column: span 2;
56
-
57
- al-icon {
58
- grid-area: icons;
59
- justify-content: center;
60
- align-items: center;
61
- }
62
-
63
- .text {
64
- grid-area: title;
65
- }
66
- }
67
- }
68
- }
69
-
70
- al-dropdown-item {
71
- margin: 0 8px;
72
- padding: 8px;
73
-
74
- &:hover,
75
- &.focused {
76
- background-color: var(--color-p-dropdown-active-item-bg);
77
- color: var(--color-p-dropdown-active-item-bg-text);
78
- }
79
-
80
- &:first-child {
81
- margin-top: 8px;
82
- }
83
-
84
- &:last-child {
85
- margin-bottom: 8px;
86
- }
87
- }
88
- }
89
-
90
- al-dropdown-item {
91
- cursor: pointer;
92
- }
93
- }
@@ -1,123 +0,0 @@
1
- /**
2
- * The <al-dropdown> element
3
- *
4
- * @author Jelle De Loecker <jelle@elevenways.be>
5
- * @since 0.3.0
6
- * @version 0.3.0
7
- */
8
- const Dropdown = Function.inherits('Alchemy.Element.Form.Base', 'Dropdown');
9
-
10
- /**
11
- * The template code
12
- *
13
- * @author Jelle De Loecker <jelle@elevenways.be>
14
- * @since 0.3.0
15
- * @version 0.3.0
16
- */
17
- Dropdown.setTemplateFile('form/elements/al_dropdown');
18
-
19
- /**
20
- * Is this dropdown open?
21
- *
22
- * @author Jelle De Loecker <jelle@elevenways.be>
23
- * @since 0.3.0
24
- * @version 0.3.0
25
- */
26
- Dropdown.defineStateVariable('is_open', {
27
- type : 'boolean',
28
- default : false,
29
- on_change : function(editor) {
30
- this.refreshDropdownPosition();
31
- },
32
- });
33
-
34
- /**
35
- * The dropdown wrapper element
36
- *
37
- * @author Jelle De Loecker <jelle@elevenways.be>
38
- * @since 0.3.0
39
- * @version 0.3.0
40
- */
41
- Dropdown.defineStateVariable('items_wrapper', {
42
- type : 'element',
43
- default : null,
44
- });
45
-
46
- /**
47
- * The last chosen item
48
- *
49
- * @author Jelle De Loecker <jelle@elevenways.be>
50
- * @since 0.3.0
51
- * @version 0.3.0
52
- */
53
- Dropdown.defineStateVariable('last_chosen_item');
54
-
55
- /**
56
- * The "selected" item, if any.
57
- * (This requires custom logic to be set)
58
- *
59
- * @author Jelle De Loecker <jelle@elevenways.be>
60
- * @since 0.3.0
61
- * @version 0.3.0
62
- */
63
- Dropdown.defineStateVariable('selected_item');
64
-
65
- /**
66
- * Toggle the dropdown state
67
- *
68
- * @author Jelle De Loecker <jelle@elevenways.be>
69
- * @since 0.3.0
70
- * @version 0.3.0
71
- */
72
- Dropdown.setMethod(function toggleDropdown() {
73
- let is_open = this.getStateOptional('is_open');
74
- is_open.value = !is_open.value;
75
- });
76
-
77
- /**
78
- * Refresh the dropdown position
79
- *
80
- * @author Jelle De Loecker <jelle@elevenways.be>
81
- * @since 0.3.0
82
- * @version 0.3.0
83
- */
84
- Dropdown.setMethod(function refreshDropdownPosition() {
85
-
86
- let is_open = this.getStateOptional('is_open');
87
-
88
- if (!is_open.value) {
89
- return;
90
- }
91
-
92
- let items_wrapper = this.getState('items_wrapper');
93
-
94
- if (!items_wrapper) {
95
- return;
96
- }
97
-
98
- let rect = this.getBoundingClientRect();
99
-
100
- items_wrapper.style.left = rect.left + 'px';
101
- items_wrapper.style.top = rect.bottom + 'px';
102
- });
103
-
104
- /**
105
- * Added to the DOM for the first time
106
- *
107
- * @author Jelle De Loecker <jelle@elevenways.be>
108
- * @since 0.3.0
109
- * @version 0.3.0
110
- */
111
- Dropdown.setMethod(function introduced() {
112
-
113
- let last_chosen_optional = this.getStateOptional('last_chosen_item');
114
-
115
- this.addEventListener('click', e => {
116
-
117
- let item = e.target.closest('al-dropdown-item');
118
-
119
- if (item) {
120
- last_chosen_optional.value = item;
121
- }
122
- });
123
- });
@@ -1,40 +0,0 @@
1
- /**
2
- * The <al-dropdown-item> element
3
- *
4
- * @author Jelle De Loecker <jelle@elevenways.be>
5
- * @since 0.3.0
6
- * @version 0.3.0
7
- */
8
- const DropdownItem = Function.inherits('Alchemy.Element.Form.Base', 'DropdownItem');
9
-
10
- /**
11
- * This has the button role
12
- *
13
- * @author Jelle De Loecker <jelle@elevenways.be>
14
- * @since 0.3.0
15
- * @version 0.3.0
16
- */
17
- DropdownItem.setRole('button');
18
-
19
- /**
20
- * Is this item selected somehow?
21
- *
22
- * @author Jelle De Loecker <jelle@elevenways.be>
23
- * @since 0.3.0
24
- * @version 0.3.0
25
- */
26
- DropdownItem.defineStateVariable('is_selected', {
27
- type : 'boolean',
28
- default : false,
29
- on_change : function onSelectedChange(value) {
30
- console.log('On change:', value);
31
- if (value) {
32
- let dropdown = this.closest('al-dropdown');
33
-
34
- if (dropdown) {
35
- let selected_item = dropdown.getStateOptional('selected_item');
36
- selected_item.value = this;
37
- }
38
- }
39
- }
40
- });
@@ -1,21 +0,0 @@
1
- <div class="dropdown-trigger-wrapper">
2
- <button
3
- type="button"
4
- :ref={% button_ref %}
5
- prop:disabled={% state:disabled{:} %}
6
- on:click={% self.toggleDropdown() %}
7
- >
8
- <slot name="dropdown-trigger"></slot>
9
- <slot name="dropdown-trigger-icon" aria-hidden="true">
10
- <al-icon icon-name="chevron-down"></al-icon>
11
- </slot>
12
- </button>
13
- </div>
14
-
15
- <div
16
- :ref={% state:items_wrapper %}
17
- class="dropdown-items-wrapper"
18
- prop:hidden={% not state:is_open{:} %}
19
- >
20
- <slot name="dropdown-items"></slot>
21
- </div>