basecoat-cli 0.1.1 → 0.2.0-beta.1

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.
@@ -17,39 +17,53 @@
17
17
  selected=None,
18
18
  name=None,
19
19
  items=None,
20
- main_attrs={},
21
20
  trigger_attrs={},
22
- content_attrs={},
21
+ popover_attrs={},
23
22
  listbox_attrs={},
24
- input_attrs={},
25
23
  search_placeholder="Search entries...",
26
24
  is_combobox=false
27
25
  ) %}
28
- <div
29
- class="popover {{ main_attrs.class }}"
30
- x-data="select('{{ name }}', '{{ selected or '' }}')"
31
- @click.away="open = false"
32
- {% if id %}id="{{ id }}"{% endif %}
33
- {% for key, value in main_attrs %}
34
- {% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
35
- {% endfor %}
36
- >
26
+ {% set id = id or ("select-" + (range(100000, 999999) | random | string)) %}
27
+
28
+ {% set first_option = [] %}
29
+ {% set selected_option = [] %}
30
+
31
+ {% for item in items %}
32
+ {% if item.type == "group" %}
33
+ {% for sub_item in item.items %}
34
+ {% if not first_option[0] %}
35
+ {% set first_option = (first_option.push(sub_item), first_option) %}
36
+ {% endif %}
37
+ {% if selected and sub_item.value == selected and not selected_option[0] %}
38
+ {% set selected_option = (selected_option.push(sub_item), selected_option) %}
39
+ {% endif %}
40
+ {% endfor %}
41
+ {% else %}
42
+ {% if not first_option[0] %}
43
+ {% set first_option = (first_option.push(item), first_option) %}
44
+ {% endif %}
45
+ {% if selected and item.value == selected and not selected_option[0] %}
46
+ {% set selected_option = (selected_option.push(item), selected_option) %}
47
+ {% endif %}
48
+ {% endif %}
49
+ {% endfor %}
50
+
51
+ {% set default_option = selected_option[0] or first_option[0] or None %}
52
+
53
+ <div class="select">
37
54
  <button
38
55
  type="button"
56
+ class="btn-outline justify-between font-normal {{ trigger_attrs.class }}"
57
+ id="{{ id }}-trigger"
58
+ popovertarget="{{ id }}"
39
59
  aria-haspopup="listbox"
40
60
  aria-expanded="false"
41
- x-bind="$trigger"
42
- {% if id %}
43
- id="{{ id }}-trigger"
44
- aria-controls="{{ id }}-content"
45
- {% endif %}
46
- class="btn-outline justify-between font-normal {{ trigger_attrs.class }}"
61
+ aria-controls="{{ id }}-listbox"
47
62
  {% for key, value in trigger_attrs %}
48
63
  {% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
49
64
  {% endfor %}
50
65
  >
51
- <div x-html="selectedLabel" class="flex items-center gap-x-2"
52
- ></div>
66
+ <span class="truncate">{{ default_option.label }}</span>
53
67
  {% if is_combobox %}
54
68
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevrons-up-down-icon lucide-chevrons-up-down text-muted-foreground opacity-50 shrink-0"><path d="m7 15 5 5 5-5"/><path d="m7 9 5-5 5 5"/></svg>
55
69
  {% else %}
@@ -57,12 +71,11 @@
57
71
  {% endif %}
58
72
  </button>
59
73
  <div
60
- data-popover
61
- aria-hidden="true"
62
- x-bind="$content"
63
- {% if id %}id="{{ id }}-content"{% endif %}
64
- {% for key, value in content_attrs %}
65
- {{ key }}="{{ value }}"
74
+ popover
75
+ id="{{ id }}"
76
+ class="popover {{ popover_attrs.class }}"
77
+ {% for key, value in popover_attrs %}
78
+ {% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
66
79
  {% endfor %}
67
80
  >
68
81
  {% if is_combobox %}
@@ -80,35 +93,33 @@
80
93
  aria-expanded="true"
81
94
  aria-controls="{{ id }}-content"
82
95
  aria-labelledby="{{ id }}-trigger"
83
- x-model="query"
84
- x-bind="$filter"
85
96
  >
86
97
  </header>
87
98
  {% endif %}
88
99
  <div
89
100
  role="listbox"
101
+ id="{{ id }}-listbox"
90
102
  aria-orientation="vertical"
103
+ aria-labelledby="{{ id }}-trigger"
91
104
  {% for key, value in listbox_attrs %}
92
105
  {{ key }}="{{ value }}"
93
106
  {% endfor %}
94
107
  >
95
- {% if items %}
96
- {{ render_select_items(items, id ~ "-items" if id else "items") }}
108
+ {% if items.length > 0 %}
109
+ {{ render_select_items(items, default_option.value, id ~ "-items" if id else "items") }}
97
110
  {% else %}
98
111
  {{ caller() if caller }}
99
112
  {% endif %}
100
113
  </div>
101
114
  </div>
102
- {% if name is defined %}
103
- <input
104
- type="hidden"
105
- name="{{ name }}"
106
- x-model="selectedValue"
107
- {% for key, value in input_attrs %}
108
- {% if key != 'name' %}{{ key }}="{{ value }}"{% endif %}
109
- {% endfor %}
110
- >
111
- {% endif %}
115
+ <input
116
+ type="hidden"
117
+ name="{{ name or id ~ '-value' }}"
118
+ value="{{ selected or '' }}"
119
+ {% for key, value in input_attrs %}
120
+ {% if key != 'name' and key != 'value' %}{{ key }}="{{ value }}"{% endif %}
121
+ {% endfor %}
122
+ >
112
123
  </div>
113
124
  {% endmacro %}
114
125
 
@@ -118,10 +129,9 @@
118
129
  @param items {array} - The array of items to render.
119
130
  @param parent_id_prefix {string} [optional] - The prefix for the item id.
120
131
  #}
121
- {% macro render_select_items(items, parent_id_prefix="items") %}
132
+ {% macro render_select_items(items, selected, parent_id_prefix="items") %}
122
133
  {% for item in items %}
123
134
  {% set item_id = parent_id_prefix ~ "-" ~ loop.index %}
124
-
125
135
  {% if item.type == "group" %}
126
136
  {% set group_label_id = item.id if item.id else "group-label-" + item_id %}
127
137
  <div
@@ -132,14 +142,16 @@
132
142
  {% endfor %}
133
143
  >
134
144
  <div role="heading" id="{{ group_label_id }}">{{ item.label }}</div>
135
- {{ render_select_items(item.items, item_id) if item.items }}
145
+ {{ render_select_items(item.items, selected, item_id) if item.items }}
136
146
  </div>
137
147
  {% elif item.type == "separator" %}
138
148
  <hr role="separator" />
139
149
  {% elif item.type == "item" or not item.type %}
140
150
  <div
151
+ id="{{ item_id }}"
141
152
  role="option"
142
153
  data-value="{{ item.value }}"
154
+ {% if selected == item.value %}aria-selected="true"{% endif %}
143
155
  {% for key, value in item.attrs %}
144
156
  {{ key }}="{{ value }}"
145
157
  {% endfor %}
@@ -23,18 +23,15 @@
23
23
  footer_attrs={},
24
24
  content_wrapper_attrs=None
25
25
  ) %}
26
- <div
26
+ <aside
27
27
  {% if id %}id="{{ id }}"{% endif %}
28
28
  class="sidebar {{ main_attrs.class }}"
29
- data-uninitialized
30
29
  data-side="{{ side if side else "left" }}"
31
30
  aria-hidden="{{ "true" if not open else "false" }}"
32
31
  {{ "inert" if not open }}
33
32
  {% for key, value in main_attrs %}
34
33
  {% if key != "class" %}{{ key }}="{{ value }}"{% endif %}
35
34
  {% endfor %}
36
- x-data="sidebar({{ "true" if open else "false" }})"
37
- x-bind="$main"
38
35
  >
39
36
  <nav
40
37
  aria-label="{{ label }}"
@@ -71,7 +68,7 @@
71
68
  </footer>
72
69
  {% endif %}
73
70
  </nav>
74
- </div>
71
+ </aside>
75
72
  {% endmacro %}
76
73
 
77
74
  {#
@@ -14,17 +14,17 @@
14
14
  @param default_tab_index {number} [optional] [default=1] - The 1-based index of the tab to be active initially.
15
15
  #}
16
16
  {% macro tabs(
17
- id,
17
+ id=None,
18
18
  tabsets=[],
19
19
  main_attrs=None,
20
20
  tablist_attrs=None,
21
21
  default_tab_index=1
22
22
  )
23
23
  %}
24
+ {% set id = id or ("tabs-" + (range(100000, 999999) | random | string)) %}
24
25
  <div
25
26
  class="tabs {{ main_attrs.class }}"
26
- x-data="tabs({{ default_tab_index - 1 }})"
27
- {% if id %}id="{{ id }}"{% endif %}
27
+ id="{{ id }}"
28
28
  {% for key, value in main_attrs %}
29
29
  {% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
30
30
  {% endfor %}
@@ -32,7 +32,6 @@
32
32
  <nav
33
33
  role="tablist"
34
34
  aria-orientation="horizontal"
35
- x-bind="$tablist"
36
35
  {% for key, value in tablist_attrs %}
37
36
  {{ key }}="{{ value }}"
38
37
  {% endfor %}
@@ -41,8 +40,8 @@
41
40
  <button
42
41
  type="button"
43
42
  role="tab"
44
- id="{{ tabset.id }}-tab-{{ loop.index }}"
45
- aria-controls="{{ tabset.id }}-panel-{{ loop.index }}"
43
+ id="{{ id }}-tab-{{ loop.index }}"
44
+ aria-controls="{{ id }}-panel-{{ loop.index }}"
46
45
  aria-selected="{{ 'true' if loop.index == default_tab_index else 'false' }}"
47
46
  tabindex="0"
48
47
  {% for key, value in tabset.tab_attrs %}
@@ -58,8 +57,8 @@
58
57
  {% if tabset.panel %}
59
58
  <div
60
59
  role="tabpanel"
61
- id="{{ tabset.id }}-panel-{{ loop.index }}"
62
- aria-labelledby="{{ tabset.id }}-tab-{{ loop.index }}"
60
+ id="{{ id }}-panel-{{ loop.index }}"
61
+ aria-labelledby="{{ id }}-tab-{{ loop.index }}"
63
62
  tabindex="-1"
64
63
  aria-selected="{{ 'true' if loop.index == default_tab_index else 'false' }}"
65
64
  {% if loop.index != default_tab_index %}hidden{% endif %}
@@ -10,16 +10,14 @@
10
10
  {% macro toaster(
11
11
  id="toaster",
12
12
  toasts=[],
13
- main_attrs=None,
14
- is_fragment=false
13
+ attrs=None
15
14
  ) %}
16
15
  <div
17
16
  id="{{ id }}"
18
17
  class="toaster"
19
- {% for key, value in main_attrs %}
18
+ {% for key, value in attrs %}
20
19
  {{ key }}="{{ value }}"
21
20
  {% endfor %}
22
- {% if is_fragment %}hx-swap-oob="beforeend"{% endif %}
23
21
  >
24
22
  {% for item in toasts %}
25
23
  {{ toast(
@@ -31,79 +29,6 @@
31
29
  ) }}
32
30
  {% endfor %}
33
31
  </div>
34
-
35
- {% if not is_fragment %}
36
- <template id="toast-template">
37
- <div
38
- class="toast"
39
- role="status"
40
- aria-atomic="true"
41
- x-bind="$toastBindings"
42
- >
43
- <div class="toast-content">
44
- <div class="flex items-center justify-between gap-x-3 p-4 [&>svg]:size-4 [&>svg]:shrink-0 [&>[role=img]]:size-4 [&>[role=img]]:shrink-0 [&>[role=img]>svg]:size-4">
45
- <template x-if="config.icon">
46
- <span aria-hidden="true" role="img" x-html="config.icon"></span>
47
- </template>
48
- <template x-if="!config.icon && config.category === 'success'">
49
- {{ toast_icons.success | safe }}
50
- </template>
51
- <template x-if="!config.icon && config.category === 'error'">
52
- {{ toast_icons.error | safe }}
53
- </template>
54
- <template x-if="!config.icon && config.category === 'info'">
55
- {{ toast_icons.info | safe }}
56
- </template>
57
- <template x-if="!config.icon && config.category === 'warning'">
58
- {{ toast_icons.warning | safe }}
59
- </template>
60
- <section class="flex-1 flex flex-col gap-0.5 items-start">
61
- <template x-if="config.title">
62
- <h2 class="font-medium" x-text="config.title"></h2>
63
- </template>
64
- <template x-if="config.description">
65
- <p class="text-muted-foreground" x-text="config.description"></p>
66
- </template>
67
- </section>
68
- <template x-if="config.action || config.cancel">
69
- <footer class="flex flex-col gap-1 self-start">
70
- <template x-if="config.action?.click">
71
- <button
72
- type="button"
73
- class="btn h-6 text-xs px-2.5 rounded-sm"
74
- @click="executeAction(config.action.click)"
75
- x-text="config.action.label"
76
- ></button>
77
- </template>
78
- <template x-if="config.action?.url">
79
- <a
80
- :href="config.action.url"
81
- class="btn h-6 text-xs px-2.5 rounded-sm"
82
- x-text="config.action.label"
83
- ></a>
84
- </template>
85
- <template x-if="config.cancel?.click">
86
- <button
87
- type="button"
88
- class="btn-outline h-6 text-xs px-2.5 rounded-sm"
89
- @click="executeAction(config.cancel.click)"
90
- x-text="config.cancel.label"
91
- ></button>
92
- </template>
93
- <template x-if="config.cancel?.url">
94
- <a
95
- :href="config.cancel.url"
96
- class="btn-outline h-6 text-xs px-2.5 rounded-sm"
97
- x-text="config.cancel.label"
98
- ></a>
99
- </template>
100
- </footer>
101
- </template>
102
- </div>
103
- </div>
104
- </div>
105
- </template>
106
- {% endif %}
107
32
  {% endmacro %}
108
33
 
109
34
  {#
@@ -134,65 +59,51 @@
134
59
  aria-atomic="true"
135
60
  aria-hidden="false"
136
61
  {% if category %}data-category="{{ category }}"{% endif %}
137
- x-data="toast({
138
- category: '{{ category }}',
139
- duration: {{ duration or 'null' }}
140
- })"
141
- x-bind="$toastBindings"
142
62
  >
143
63
  <div class="toast-content">
144
- <div class="flex items-center justify-between gap-x-3 p-4 [&>svg]:size-4 [&>svg]:shrink-0 [&>[role=img]]:size-4 [&>[role=img]]:shrink-0 [&>[role=img]>svg]:size-4">
145
- {% if category in ["error", "success", "info", "warning"] %}
146
- {{ toast_icons[category] | safe }}
64
+ {% if category in ["error", "success", "info", "warning"] %}
65
+ {% if category == "success" %}
66
+ {% lucide "circle-check" %}
67
+ {% elif category == "error" %}
68
+ {% lucide "circle-x" %}
69
+ {% elif category == "info" %}
70
+ {% lucide "info" %}
71
+ {% elif category == "warning" %}
72
+ {% lucide "triangle-alert" %}
147
73
  {% endif %}
148
- <section class="flex-1 flex flex-col gap-0.5 items-start">
149
- {% if title %}
150
- <h2 class="font-medium">{{ title }}</h2>
74
+ {% endif %}
75
+ <section>
76
+ {% if title %}<h2>{{ title }}</h2>{% endif %}
77
+ {% if description %}<p>{{ description }}</p>{% endif %}
78
+ </section>
79
+ {% if action or cancel %}
80
+ <footer>
81
+ {% if action %}
82
+ {% if action.href %}
83
+ <a
84
+ href="{{ action.href }}"
85
+ class="btn-sm"
86
+ data-toast-action
87
+ >{{ action.label }}</a>
88
+ {% else %}
89
+ <button
90
+ type="button"
91
+ class="btn"
92
+ data-toast-action
93
+ {% if action.onclick %}onclick="{{ action.onclick }}"{% endif %}
94
+ >{{ action.label }}</button>
95
+ {% endif %}
151
96
  {% endif %}
152
- {% if description %}
153
- <p class="text-muted-foreground">{{ description }}</p>
97
+ {% if cancel %}
98
+ <button
99
+ type="button"
100
+ class="btn-sm-outline"
101
+ data-toast-cancel
102
+ {% if cancel.onclick %}onclick="{{ cancel.onclick }}"{% endif %}
103
+ >{{ cancel.label }}</button>
154
104
  {% endif %}
155
- </section>
156
- {% if action or cancel %}
157
- <footer class="flex flex-col gap-1 self-start">
158
- {% if action %}
159
- {% if action.click %}
160
- <button
161
- type="button"
162
- class="btn h-6 text-xs px-2.5 rounded-sm"
163
- @click="{{ action.click }}"
164
- >{{ action.label }}</button>
165
- {% elif action.url %}
166
- <a
167
- href="{{ action.url }}"
168
- class="btn h-6 text-xs px-2.5 rounded-sm"
169
- >{{ action.label }}</a>
170
- {% endif %}
171
- {% endif %}
172
- {% if cancel %}
173
- {% if cancel.click %}
174
- <button
175
- type="button"
176
- class="btn-outline h-6 text-xs px-2.5 rounded-sm"
177
- @click="{{ cancel.click }}"
178
- >{{ cancel.label }}</button>
179
- {% elif cancel.url %}
180
- <a
181
- href="{{ cancel.url }}"
182
- class="btn-outline h-6 text-xs px-2.5 rounded-sm"
183
- >{{ toast.cancel.label }}</a>
184
- {% endif %}
185
- {% endif %}
186
- </footer>
187
- {% endif %}
188
- </div>
105
+ </footer>
106
+ {% endif %}
189
107
  </div>
190
108
  </div>
191
- {% endmacro %}
192
-
193
- {% set toast_icons = {
194
- 'success': '<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-check-icon lucide-circle-check"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>',
195
- 'error': '<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-x-icon lucide-circle-x"><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/></svg>',
196
- 'info': '<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-info-icon lucide-info"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>',
197
- 'warning': '<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-triangle-alert-icon lucide-triangle-alert"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>'
198
- } %}
109
+ {% endmacro %}
package/dist/index.js CHANGED
@@ -62,17 +62,17 @@ async function ensureConfiguration() {
62
62
  const pathPrompts = [];
63
63
  if (!config.templateDest || config.templateDest === DEFAULT_CONFIG.templateDest) {
64
64
  pathPrompts.push({
65
- type: 'input',
66
- name: 'templateDest',
67
- message: 'Where should template files be placed?',
65
+ type: 'input',
66
+ name: 'templateDest',
67
+ message: 'Where should template files be placed?',
68
68
  default: DEFAULT_CONFIG.templateDest,
69
69
  });
70
70
  }
71
71
  if (!config.scriptDest || config.scriptDest === DEFAULT_CONFIG.scriptDest) {
72
72
  pathPrompts.push({
73
- type: 'input',
74
- name: 'scriptDest',
75
- message: 'Where should script files be placed?',
73
+ type: 'input',
74
+ name: 'scriptDest',
75
+ message: 'Where should script files be placed?',
76
76
  default: DEFAULT_CONFIG.scriptDest,
77
77
  });
78
78
  }
@@ -108,7 +108,7 @@ async function addComponent(componentName) {
108
108
  }
109
109
  if (!scriptExists) {
110
110
  console.error(` Error: Script file for component '${componentName}' not found in CLI assets. Searched: ${scriptSource}`);
111
- }
111
+ }
112
112
  if (!templateExists || !scriptExists) return; // Skip this component if sources are missing
113
113
 
114
114
  await fs.ensureDir(path.dirname(templateDestPath));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "basecoat-cli",
3
- "version": "0.1.1",
3
+ "version": "0.2.0-beta.1",
4
4
  "description": "Add Basecoat components to your project",
5
5
  "author": "hunvreus",
6
6
  "license": "MIT",
@@ -1,54 +0,0 @@
1
- window.basecoat = window.basecoat || {};
2
- window.basecoat.registerDialog = function(Alpine) {
3
- if (Alpine.components && Alpine.components.dialog) return;
4
-
5
- Alpine.data('dialog', (initialOpen = false, initialCloseOnOverlayClick = true) => ({
6
- id: null,
7
- open: false,
8
- closeOnOverlayClick: true,
9
-
10
- init() {
11
- this.id = this.$el.id;
12
- if (!this.id) {
13
- console.warn('Dialog component initialized without an `id`. This may cause issues with event targeting and accessibility.');
14
- }
15
- this.open = initialOpen;
16
- this.closeOnOverlayClick = initialCloseOnOverlayClick;
17
- },
18
- show() {
19
- if (!this.open) {
20
- this.open = true;
21
- this.$nextTick(() => {
22
- this.$el.dispatchEvent(new CustomEvent('dialog:opened', { bubbles: true, detail: { id: this.id } }));
23
- setTimeout(() => {
24
- const focusTarget = this.$refs.focusOnOpen || this.$el.querySelector('[role="dialog"]');
25
- if (focusTarget) focusTarget.focus();
26
- }, 50);
27
- });
28
- }
29
- },
30
- hide() {
31
- if (this.open) {
32
- this.open = false;
33
- this.$nextTick(() => {
34
- this.$el.dispatchEvent(new CustomEvent('dialog:closed', { bubbles: true, detail: { id: this.id } }));
35
- });
36
- }
37
- },
38
-
39
- $main: {
40
- '@dialog:open.window'(e) { if (e.detail && e.detail.id === this.id) this.show() },
41
- '@dialog:close.window'(e) { if (e.detail && e.detail.id === this.id) this.hide() },
42
- '@keydown.escape.window'() { this.open && this.hide() },
43
- },
44
- $trigger: {
45
- '@click'() { this.show() },
46
- ':aria-expanded'() { return this.open }
47
- },
48
- $content: {
49
- ':inert'() { return !this.open },
50
- '@click.self'() { if (this.closeOnOverlayClick) this.hide() },
51
- 'x-cloak': ''
52
- }
53
- }));
54
- };
@@ -1,26 +0,0 @@
1
- window.basecoat = window.basecoat || {};
2
- window.basecoat.registerPopover = function(Alpine) {
3
- if (Alpine.components && Alpine.components.popover) return;
4
-
5
- Alpine.data('popover', () => ({
6
- open: false,
7
-
8
- $trigger: {
9
- '@click'() { this.open = !this.open },
10
- '@keydown.escape.prevent'() {
11
- this.open = false;
12
- this.$refs.trigger.focus();
13
- },
14
- ':aria-expanded'() { return this.open },
15
- 'x-ref': 'trigger'
16
- },
17
- $content: {
18
- '@keydown.escape.prevent'() {
19
- this.open = false;
20
- this.$refs.trigger.focus();
21
- },
22
- ':aria-hidden'() { return !this.open },
23
- 'x-cloak': ''
24
- },
25
- }));
26
- };