@fleetbase/ember-ui 0.3.22 → 0.3.24

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 (46) hide show
  1. package/addon/components/layout/header/smart-nav-menu/dropdown.hbs +77 -68
  2. package/addon/components/layout/header/smart-nav-menu/dropdown.js +7 -54
  3. package/addon/components/template-builder/canvas.hbs +23 -0
  4. package/addon/components/template-builder/canvas.js +116 -0
  5. package/addon/components/template-builder/element-renderer.hbs +126 -0
  6. package/addon/components/template-builder/element-renderer.js +398 -0
  7. package/addon/components/template-builder/layers-panel.hbs +99 -0
  8. package/addon/components/template-builder/layers-panel.js +146 -0
  9. package/addon/components/template-builder/properties-panel/field.hbs +7 -0
  10. package/addon/components/template-builder/properties-panel/field.js +9 -0
  11. package/addon/components/template-builder/properties-panel/section.hbs +24 -0
  12. package/addon/components/template-builder/properties-panel/section.js +19 -0
  13. package/addon/components/template-builder/properties-panel.hbs +576 -0
  14. package/addon/components/template-builder/properties-panel.js +413 -0
  15. package/addon/components/template-builder/queries-panel.hbs +84 -0
  16. package/addon/components/template-builder/queries-panel.js +88 -0
  17. package/addon/components/template-builder/query-form.hbs +260 -0
  18. package/addon/components/template-builder/query-form.js +309 -0
  19. package/addon/components/template-builder/toolbar.hbs +134 -0
  20. package/addon/components/template-builder/toolbar.js +106 -0
  21. package/addon/components/template-builder/variable-picker.hbs +210 -0
  22. package/addon/components/template-builder/variable-picker.js +181 -0
  23. package/addon/components/template-builder.hbs +119 -0
  24. package/addon/components/template-builder.js +567 -0
  25. package/addon/helpers/string-starts-with.js +14 -0
  26. package/addon/services/template-builder.js +72 -0
  27. package/addon/styles/addon.css +1 -0
  28. package/addon/styles/components/badge.css +66 -12
  29. package/addon/styles/components/smart-nav-menu.css +35 -29
  30. package/addon/styles/components/template-builder.css +297 -0
  31. package/addon/utils/get-currency.js +1 -1
  32. package/app/components/template-builder/canvas.js +1 -0
  33. package/app/components/template-builder/element-renderer.js +1 -0
  34. package/app/components/template-builder/layers-panel.js +1 -0
  35. package/app/components/template-builder/properties-panel/field.js +1 -0
  36. package/app/components/template-builder/properties-panel/section.js +1 -0
  37. package/app/components/template-builder/properties-panel.js +1 -0
  38. package/app/components/template-builder/queries-panel.js +1 -0
  39. package/app/components/template-builder/query-form.js +1 -0
  40. package/app/components/template-builder/toolbar.js +1 -0
  41. package/app/components/template-builder/variable-picker.js +1 -0
  42. package/app/components/template-builder.js +1 -0
  43. package/app/helpers/string-starts-with.js +1 -0
  44. package/app/services/template-builder.js +1 -0
  45. package/package.json +3 -2
  46. package/tsconfig.declarations.json +8 -8
@@ -0,0 +1,14 @@
1
+ import { helper } from '@ember/component/helper';
2
+
3
+ /**
4
+ * {{string-starts-with str prefix}}
5
+ *
6
+ * Returns true if `str` starts with `prefix`. Safe against null/undefined.
7
+ *
8
+ * Example:
9
+ * {{#if (string-starts-with query.uuid "_new_")}}
10
+ */
11
+ export default helper(function stringStartsWith([str, prefix]) {
12
+ if (typeof str !== 'string' || typeof prefix !== 'string') return false;
13
+ return str.startsWith(prefix);
14
+ });
@@ -0,0 +1,72 @@
1
+ import Service from '@ember/service';
2
+ import { tracked } from '@glimmer/tracking';
3
+
4
+ /**
5
+ * TemplateBuildService
6
+ *
7
+ * A singleton service that extensions can inject to register resource types
8
+ * available in the TemplateQuery form. Each extension registers its own
9
+ * resource types (Fleetbase model classes) so the template builder knows
10
+ * what models can be queried at render time.
11
+ *
12
+ * Usage in an extension initializer:
13
+ *
14
+ * // addon/instance-initializers/register-template-resources.js
15
+ * export function initialize(appInstance) {
16
+ * const templateBuilder = appInstance.lookup('service:template-builder');
17
+ * templateBuilder.registerResourceTypes([
18
+ * { label: 'Order', value: 'Fleetbase\\FleetOps\\Models\\Order', icon: 'route' },
19
+ * { label: 'Driver', value: 'Fleetbase\\FleetOps\\Models\\Driver', icon: 'id-card' },
20
+ * { label: 'Vehicle', value: 'Fleetbase\\FleetOps\\Models\\Vehicle', icon: 'truck' },
21
+ * ]);
22
+ * }
23
+ * export default { initialize };
24
+ *
25
+ * Each resource type object must have:
26
+ * - `label` {string} Human-readable name shown in the picker grid
27
+ * - `value` {string} Fully-qualified PHP class name sent to the backend
28
+ * - `icon` {string} FontAwesome icon name (without the `fa-` prefix)
29
+ *
30
+ * The TemplateBuilder::QueryForm component reads `resourceTypes` from this
31
+ * service and merges them with any types passed via `@resourceTypes` argument,
32
+ * with the argument taking precedence (override).
33
+ */
34
+ export default class TemplateBuildService extends Service {
35
+ /**
36
+ * Registered resource types from all extensions.
37
+ * @type {Array<{label: string, value: string, icon: string}>}
38
+ */
39
+ @tracked _resourceTypes = [];
40
+
41
+ /**
42
+ * Register one or more resource types from an extension.
43
+ * Duplicate values (by `value` field) are ignored.
44
+ *
45
+ * @param {Array<{label: string, value: string, icon: string}>} types
46
+ */
47
+ registerResourceTypes(types = []) {
48
+ const existing = new Set(this._resourceTypes.map((t) => t.value));
49
+ const newTypes = types.filter((t) => t.value && !existing.has(t.value));
50
+ if (newTypes.length) {
51
+ this._resourceTypes = [...this._resourceTypes, ...newTypes];
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Unregister resource types by value. Useful when an extension is torn down.
57
+ *
58
+ * @param {Array<string>} values
59
+ */
60
+ unregisterResourceTypes(values = []) {
61
+ const toRemove = new Set(values);
62
+ this._resourceTypes = this._resourceTypes.filter((t) => !toRemove.has(t.value));
63
+ }
64
+
65
+ /**
66
+ * All currently registered resource types.
67
+ * @returns {Array<{label: string, value: string, icon: string}>}
68
+ */
69
+ get resourceTypes() {
70
+ return this._resourceTypes;
71
+ }
72
+ }
@@ -53,6 +53,7 @@
53
53
  @import 'components/query-builder.css';
54
54
  @import 'components/activity-log.css';
55
55
  @import 'components/smart-nav-menu.css';
56
+ @import 'components/template-builder.css';
56
57
 
57
58
  /** Third party */
58
59
  @import "ember-basic-dropdown/vendor/ember-basic-dropdown.css";
@@ -46,7 +46,11 @@
46
46
  .status-badge.dispatched-status-badge > span,
47
47
  .status-badge.operational-status-badge > span,
48
48
  .status-badge.active-status-badge > span,
49
- .status-badge.completed-status-badge > span {
49
+ .status-badge.completed-status-badge > span,
50
+ /* ── Invoice statuses ── */
51
+ .status-badge.paid-status-badge > span,
52
+ .status-badge.settled-status-badge > span,
53
+ .status-badge.captured-status-badge > span {
50
54
  @apply bg-green-800 border-green-700 text-green-100;
51
55
  }
52
56
 
@@ -67,7 +71,10 @@
67
71
  .status-badge.dispatched-status-badge > span svg,
68
72
  .status-badge.operational-status-badge > span svg,
69
73
  .status-badge.active-status-badge > span svg,
70
- .status-badge.completed-status-badge > span svg {
74
+ .status-badge.completed-status-badge > span svg,
75
+ .status-badge.paid-status-badge > span svg,
76
+ .status-badge.settled-status-badge > span svg,
77
+ .status-badge.captured-status-badge > span svg {
71
78
  @apply text-green-300;
72
79
  }
73
80
 
@@ -153,7 +160,13 @@
153
160
  .status-badge.inactive-status-badge > span,
154
161
  .status-badge.failed-status-badge > span,
155
162
  .status-badge.cancelled-status-badge > span,
156
- .status-badge.canceled-status-badge > span {
163
+ .status-badge.canceled-status-badge > span,
164
+ /* ── Invoice / transaction terminal-failure statuses ── */
165
+ .status-badge.overdue-status-badge > span,
166
+ .status-badge.void-status-badge > span,
167
+ .status-badge.voided-status-badge > span,
168
+ .status-badge.reversed-status-badge > span,
169
+ .status-badge.chargeback-status-badge > span {
157
170
  @apply bg-red-800 border-red-700 text-red-100;
158
171
  }
159
172
 
@@ -172,7 +185,12 @@
172
185
  .status-badge.disputed-status-badge > span svg,
173
186
  .status-badge.failed-status-badge > span svg,
174
187
  .status-badge.cancelled-status-badge > span svg,
175
- .status-badge.canceled-status-badge > span svg {
188
+ .status-badge.canceled-status-badge > span svg,
189
+ .status-badge.overdue-status-badge > span svg,
190
+ .status-badge.void-status-badge > span svg,
191
+ .status-badge.voided-status-badge > span svg,
192
+ .status-badge.reversed-status-badge > span svg,
193
+ .status-badge.chargeback-status-badge > span svg {
176
194
  @apply text-red-300;
177
195
  }
178
196
 
@@ -196,7 +214,13 @@
196
214
  .status-badge.trial-status-badge > span,
197
215
  .status-badge.trialing-status-badge > span,
198
216
  .status-badge.grace-period-status-badge > span,
199
- .status-badge.pending-status-badge > span {
217
+ .status-badge.pending-status-badge > span,
218
+ /* ── Invoice statuses requiring attention ── */
219
+ .status-badge.partial-status-badge > span,
220
+ .status-badge.partially-paid-status-badge > span,
221
+ .status-badge.sent-status-badge > span,
222
+ .status-badge.viewed-status-badge > span,
223
+ .status-badge.expired-status-badge > span {
200
224
  @apply bg-yellow-700 border-yellow-700 text-yellow-100;
201
225
  }
202
226
 
@@ -220,7 +244,12 @@
220
244
  .status-badge.trial-status-badge > span svg,
221
245
  .status-badge.trialing-status-badge > span svg,
222
246
  .status-badge.grace-period-status-badge > span svg,
223
- .status-badge.pending-status-badge > span svg {
247
+ .status-badge.pending-status-badge > span svg,
248
+ .status-badge.partial-status-badge > span svg,
249
+ .status-badge.partially-paid-status-badge > span svg,
250
+ .status-badge.sent-status-badge > span svg,
251
+ .status-badge.viewed-status-badge > span svg,
252
+ .status-badge.expired-status-badge > span svg {
224
253
  @apply text-yellow-300;
225
254
  }
226
255
 
@@ -229,7 +258,11 @@
229
258
  .status-badge.operational-suggestion-status-badge > span,
230
259
  .status-badge.dispatched-status-badge > span,
231
260
  .status-badge.matched-status-badge > span,
232
- .status-badge.assigned-status-badge > span {
261
+ .status-badge.assigned-status-badge > span,
262
+ /* ── Transaction type labels ── */
263
+ .status-badge.invoice-payment-status-badge > span,
264
+ .status-badge.revenue-recognition-status-badge > span,
265
+ .status-badge.journal-entry-status-badge > span {
233
266
  @apply bg-indigo-800 border-indigo-700 text-indigo-100;
234
267
  }
235
268
 
@@ -238,7 +271,10 @@
238
271
  .status-badge.operational-suggestion-status-badge > span svg,
239
272
  .status-badge.dispatched-status-badge > span svg,
240
273
  .status-badge.matched-status-badge > span svg,
241
- .status-badge.assigned-status-badge > span svg {
274
+ .status-badge.assigned-status-badge > span svg,
275
+ .status-badge.invoice-payment-status-badge > span svg,
276
+ .status-badge.revenue-recognition-status-badge > span svg,
277
+ .status-badge.journal-entry-status-badge > span svg {
242
278
  @apply text-indigo-300;
243
279
  }
244
280
 
@@ -251,7 +287,12 @@
251
287
  .status-badge.triage-status-badge > span,
252
288
  .status-badge.alerted-status-badge > span,
253
289
  .status-badge.flagged-status-badge > span,
254
- .status-badge.medium-status-badge > span {
290
+ .status-badge.medium-status-badge > span,
291
+ /* ── Transaction processing statuses ── */
292
+ .status-badge.processing-status-badge > span,
293
+ .status-badge.authorized-status-badge > span,
294
+ .status-badge.requires-action-status-badge > span,
295
+ .status-badge.requires-capture-status-badge > span {
255
296
  @apply bg-orange-700 border-orange-700 text-orange-100;
256
297
  }
257
298
 
@@ -264,7 +305,11 @@
264
305
  .status-badge.triage-status-badge > span svg,
265
306
  .status-badge.alerted-status-badge > span svg,
266
307
  .status-badge.flagged-status-badge > span svg,
267
- .status-badge.medium-status-badge > span svg {
308
+ .status-badge.medium-status-badge > span svg,
309
+ .status-badge.processing-status-badge > span svg,
310
+ .status-badge.authorized-status-badge > span svg,
311
+ .status-badge.requires-action-status-badge > span svg,
312
+ .status-badge.requires-capture-status-badge > span svg {
268
313
  @apply text-orange-300;
269
314
  }
270
315
 
@@ -274,7 +319,12 @@
274
319
  .status-badge.low-status-badge > span,
275
320
  .status-badge.approved-status-badge > span,
276
321
  .status-badge.info-status-badge > span,
277
- .status-badge.in-progress-status-badge > span {
322
+ .status-badge.in-progress-status-badge > span,
323
+ /* ── Transaction direction indicators ── */
324
+ .status-badge.credit-status-badge > span,
325
+ .status-badge.debit-status-badge > span,
326
+ .status-badge.refunded-status-badge > span,
327
+ .status-badge.refund-status-badge > span {
278
328
  @apply bg-blue-800 border-blue-700 text-blue-100;
279
329
  }
280
330
 
@@ -284,7 +334,11 @@
284
334
  .status-badge.loq-status-badge > span svg,
285
335
  .status-badge.approved-status-badge > span svg,
286
336
  .status-badge.info-status-badge > span svg,
287
- .status-badge.in-progress-status-badge > span svg {
337
+ .status-badge.in-progress-status-badge > span svg,
338
+ .status-badge.credit-status-badge > span svg,
339
+ .status-badge.debit-status-badge > span svg,
340
+ .status-badge.refunded-status-badge > span svg,
341
+ .status-badge.refund-status-badge > span svg {
288
342
  @apply text-blue-300;
289
343
  }
290
344
 
@@ -169,13 +169,22 @@
169
169
 
170
170
  /* ── Extension card ─────────────────────────────────────────────────────────── */
171
171
 
172
+ /* Wrapper that holds the card link + absolutely-positioned pin button */
173
+ .snm-dropdown-card-wrap {
174
+ position: relative;
175
+ }
176
+
172
177
  .snm-dropdown-card {
173
178
  @apply flex flex-col rounded-lg;
174
179
  padding: 7px 10px;
175
180
  background-color: #111827; /* gray-900 */
176
181
  border: 1px solid #1f2937; /* gray-800 – darker but lighter than bg */
177
182
  transition: border-color 0.15s ease, background-color 0.15s ease;
178
- position: relative;
183
+ text-decoration: none;
184
+ color: inherit;
185
+ display: flex;
186
+ width: 100%;
187
+ box-sizing: border-box;
179
188
  }
180
189
 
181
190
  .snm-dropdown-card:hover {
@@ -183,36 +192,29 @@
183
192
  background-color: #1a2332; /* slightly lighter than gray-900 */
184
193
  }
185
194
 
186
- /* Card header row: icon + title link + pin button */
195
+ /* Card header row: icon + title + pin button */
187
196
  .snm-dropdown-card-header {
188
197
  @apply flex items-center;
189
198
  gap: 0;
190
199
  margin-bottom: 0;
191
200
  }
192
201
 
193
- /* The main extension link inside a card */
194
- .snm-dropdown-card-link {
195
- @apply flex items-center flex-1 text-sm font-medium;
196
- color: #e5e7eb; /* gray-200 */
197
- text-decoration: none;
198
- min-width: 0;
199
- cursor: pointer;
200
- border: none;
201
- background: none;
202
- padding: 0;
203
- }
204
-
205
- .snm-dropdown-card-link:hover {
206
- color: #f9fafb; /* gray-50 */
207
- }
208
-
209
- .snm-dropdown-card-link-wrapper {
210
- @apply flex flex-1;
211
- min-width: 0;
202
+ /* Pin button is a sibling of the card link, absolutely positioned top-right
203
+ so it floats above the card and receives its own clicks */
204
+ .snm-dropdown-pin-btn {
205
+ position: absolute;
206
+ top: 6px;
207
+ right: 6px;
208
+ z-index: 1;
212
209
  }
213
210
 
214
- .snm-dropdown-card-link-wrapper .snm-dropdown-card-link {
215
- width: 100%;
211
+ /* Card-as-link: the card itself is the <LinkToExternal> or <a> */
212
+ a.snm-dropdown-card,
213
+ .snm-dropdown-card[href] {
214
+ display: flex;
215
+ text-decoration: none;
216
+ color: inherit;
217
+ cursor: pointer;
216
218
  }
217
219
 
218
220
  .snm-dropdown-card-icon {
@@ -250,12 +252,13 @@
250
252
  }
251
253
 
252
254
  /* Pin button on card – always visible at low opacity, brightens on hover */
253
- .snm-dropdown-card .snm-dropdown-pin-btn {
254
- opacity: 0.35;
255
+ .snm-dropdown-card-wrap .snm-dropdown-pin-btn {
256
+ opacity: 0;
255
257
  pointer-events: auto;
258
+ transition: opacity 0.15s ease;
256
259
  }
257
260
 
258
- .snm-dropdown-card:hover .snm-dropdown-pin-btn {
261
+ .snm-dropdown-card-wrap:hover .snm-dropdown-pin-btn {
259
262
  opacity: 1;
260
263
  }
261
264
 
@@ -787,11 +790,13 @@ body[data-theme='light'] .snm-dropdown-card:hover {
787
790
  background-color: #f3f4f6; /* gray-100 */
788
791
  }
789
792
 
790
- body[data-theme='light'] .snm-dropdown-card-link {
793
+ body[data-theme='light'] a.snm-dropdown-card,
794
+ body[data-theme='light'] .snm-dropdown-card[href] {
791
795
  color: #374151; /* gray-700 */
792
796
  }
793
797
 
794
- body[data-theme='light'] .snm-dropdown-card-link:hover {
798
+ body[data-theme='light'] a.snm-dropdown-card:hover,
799
+ body[data-theme='light'] .snm-dropdown-card[href]:hover {
795
800
  color: #111827; /* gray-900 */
796
801
  }
797
802
 
@@ -799,7 +804,8 @@ body[data-theme='light'] .snm-dropdown-card-icon {
799
804
  color: #6b7280; /* gray-500 */
800
805
  }
801
806
 
802
- body[data-theme='light'] .snm-dropdown-card-link:hover .snm-dropdown-card-icon {
807
+ body[data-theme='light'] a.snm-dropdown-card:hover .snm-dropdown-card-icon,
808
+ body[data-theme='light'] .snm-dropdown-card[href]:hover .snm-dropdown-card-icon {
803
809
  color: #2563eb; /* blue-600 */
804
810
  }
805
811
 
@@ -0,0 +1,297 @@
1
+ /* =============================================================================
2
+ Template Builder
3
+ ============================================================================= */
4
+
5
+ /* Root layout */
6
+ .tb-root {
7
+ font-family: Inter, system-ui, -apple-system, sans-serif;
8
+ font-size: 13px;
9
+ }
10
+
11
+ /* ─── Canvas ─────────────────────────────────────────────────────────────── */
12
+
13
+ .tb-canvas {
14
+ box-shadow: 0 4px 24px 0 rgba(0, 0, 0, 0.12), 0 1px 4px 0 rgba(0, 0, 0, 0.08);
15
+ border-radius: 2px;
16
+ flex-shrink: 0;
17
+ }
18
+
19
+ body[data-theme='dark'] .tb-canvas {
20
+ box-shadow: 0 4px 24px 0 rgba(0, 0, 0, 0.4), 0 1px 4px 0 rgba(0, 0, 0, 0.2);
21
+ }
22
+
23
+ /* ─── Elements ───────────────────────────────────────────────────────────── */
24
+
25
+ .tb-element {
26
+ box-sizing: border-box;
27
+ user-select: none;
28
+ touch-action: none; /* required for interact.js */
29
+ }
30
+
31
+ /* Selection handles (corner dots) */
32
+ .tb-element-handle {
33
+ position: absolute;
34
+ width: 8px;
35
+ height: 8px;
36
+ background: #3b82f6;
37
+ border: 2px solid #ffffff;
38
+ border-radius: 50%;
39
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
40
+ z-index: 9999;
41
+ }
42
+
43
+ .tb-handle-nw {
44
+ top: -4px;
45
+ left: -4px;
46
+ cursor: nw-resize;
47
+ }
48
+ .tb-handle-ne {
49
+ top: -4px;
50
+ right: -4px;
51
+ cursor: ne-resize;
52
+ }
53
+ .tb-handle-sw {
54
+ bottom: -4px;
55
+ left: -4px;
56
+ cursor: sw-resize;
57
+ }
58
+ .tb-handle-se {
59
+ bottom: -4px;
60
+ right: -4px;
61
+ cursor: se-resize;
62
+ }
63
+
64
+ /* ─── Toolbar ────────────────────────────────────────────────────────────── */
65
+
66
+ .tb-toolbar {
67
+ min-height: 44px;
68
+ flex-shrink: 0;
69
+ }
70
+
71
+ .tb-toolbar-btn {
72
+ cursor: pointer;
73
+ border: none;
74
+ background: transparent;
75
+ outline: none;
76
+ }
77
+
78
+ .tb-toolbar-btn:focus-visible {
79
+ outline: 2px solid #3b82f6;
80
+ outline-offset: 1px;
81
+ }
82
+
83
+ /* ─── Panels ─────────────────────────────────────────────────────────────── */
84
+
85
+ .tb-panel-left,
86
+ .tb-panel-right {
87
+ min-width: 0;
88
+ }
89
+
90
+ .tb-layers-panel,
91
+ .tb-properties-panel {
92
+ font-size: 12px;
93
+ }
94
+
95
+ /* Layer row active state */
96
+ .tb-layer-row:focus-visible {
97
+ outline: 2px solid #3b82f6;
98
+ outline-offset: -2px;
99
+ }
100
+
101
+ /* ─── Properties Panel ───────────────────────────────────────────────────── */
102
+
103
+ .tb-prop-section {
104
+ /* intentionally minimal */
105
+ }
106
+
107
+ .tb-prop-field {
108
+ display: flex;
109
+ flex-direction: column;
110
+ }
111
+
112
+ /* ─── Form inputs ────────────────────────────────────────────────────────── */
113
+
114
+ /*
115
+ * .tb-input is the shared class for ALL form controls in the properties panel:
116
+ * <input type="text">, <input type="number">, <select>, <textarea>.
117
+ * Every property below is declared with !important on the type-specific
118
+ * overrides so that browser UA stylesheets (which reset font/color on
119
+ * <input type="number"> and <select>) cannot win.
120
+ */
121
+ .tb-input {
122
+ width: 100%;
123
+ height: 26px;
124
+ padding: 0 6px;
125
+ font-family: inherit;
126
+ font-size: 11px;
127
+ line-height: 26px;
128
+ color: #374151;
129
+ border: 1px solid #d1d5db;
130
+ border-radius: 4px;
131
+ background-color: #f9fafb;
132
+ outline: none;
133
+ box-sizing: border-box;
134
+ transition: border-color 0.15s;
135
+ /* Strip browser-specific chrome so all control types look identical */
136
+ -webkit-appearance: none;
137
+ -moz-appearance: none;
138
+ appearance: none;
139
+ }
140
+
141
+ /* Restore the native select arrow while keeping everything else uniform */
142
+ select.tb-input {
143
+ -webkit-appearance: auto;
144
+ -moz-appearance: auto;
145
+ appearance: auto;
146
+ padding-right: 4px;
147
+ /* Explicitly re-state visual properties so the appearance reset above
148
+ does not cause browsers to fall back to their own defaults */
149
+ font-size: 11px;
150
+ color: #374151;
151
+ border-radius: 4px;
152
+ }
153
+
154
+ .tb-input:focus {
155
+ border-color: #3b82f6;
156
+ background-color: #ffffff;
157
+ }
158
+
159
+ /* Dark mode */
160
+ body[data-theme='dark'] .tb-input {
161
+ border-color: #374151;
162
+ background-color: #1f2937;
163
+ color: #d1d5db;
164
+ }
165
+
166
+ body[data-theme='dark'] select.tb-input {
167
+ color: #d1d5db;
168
+ }
169
+
170
+ body[data-theme='dark'] .tb-input:focus {
171
+ border-color: #3b82f6;
172
+ background-color: #111827;
173
+ }
174
+
175
+ /*
176
+ * Number inputs: restore the spinner but keep font/color/radius consistent.
177
+ * -webkit-appearance: textfield strips the spinner on WebKit; using
178
+ * "inner-spin-button" on the pseudo-element re-adds it without re-applying
179
+ * the full native number-input chrome.
180
+ */
181
+ .tb-input[type='number'] {
182
+ -webkit-appearance: textfield;
183
+ -moz-appearance: textfield;
184
+ appearance: textfield;
185
+ padding-right: 2px;
186
+ /* Re-declare so UA overrides cannot win */
187
+ font-size: 11px;
188
+ color: #374151;
189
+ border-radius: 4px;
190
+ }
191
+
192
+ body[data-theme='dark'] .tb-input[type='number'] {
193
+ color: #d1d5db;
194
+ }
195
+
196
+ .tb-input[type='number']::-webkit-inner-spin-button,
197
+ .tb-input[type='number']::-webkit-outer-spin-button {
198
+ -webkit-appearance: inner-spin-button;
199
+ opacity: 1;
200
+ height: 24px;
201
+ cursor: pointer;
202
+ }
203
+
204
+ /* Textarea variant — allow vertical resize, auto height */
205
+ textarea.tb-input {
206
+ height: auto;
207
+ line-height: 1.4;
208
+ padding: 4px 6px;
209
+ resize: vertical;
210
+ font-size: 11px;
211
+ color: #374151;
212
+ border-radius: 4px;
213
+ }
214
+
215
+ body[data-theme='dark'] textarea.tb-input {
216
+ color: #d1d5db;
217
+ }
218
+
219
+ /* ─── Colour swatch input ────────────────────────────────────────────────── */
220
+
221
+ .tb-color-input {
222
+ width: 100%;
223
+ height: 28px;
224
+ padding: 1px 2px;
225
+ border: 1px solid #d1d5db;
226
+ border-radius: 4px;
227
+ background: none;
228
+ cursor: pointer;
229
+ }
230
+
231
+ body[data-theme='dark'] .tb-color-input {
232
+ border-color: #374151;
233
+ }
234
+
235
+ /* ─── Icon buttons ───────────────────────────────────────────────────────── */
236
+
237
+ .tb-icon-btn {
238
+ display: inline-flex;
239
+ align-items: center;
240
+ justify-content: center;
241
+ padding: 4px 6px;
242
+ border: 1px solid #d1d5db;
243
+ border-radius: 4px;
244
+ background: #f9fafb;
245
+ color: #6b7280;
246
+ cursor: pointer;
247
+ transition: background 0.15s, color 0.15s;
248
+ flex-shrink: 0;
249
+ }
250
+
251
+ .tb-icon-btn:hover {
252
+ background: #eff6ff;
253
+ color: #3b82f6;
254
+ border-color: #bfdbfe;
255
+ }
256
+
257
+ body[data-theme='dark'] .tb-icon-btn {
258
+ border-color: #374151;
259
+ background: #1f2937;
260
+ color: #9ca3af;
261
+ }
262
+
263
+ body[data-theme='dark'] .tb-icon-btn:hover {
264
+ background: #1e3a5f;
265
+ color: #60a5fa;
266
+ border-color: #1d4ed8;
267
+ }
268
+
269
+ /* ─── Variable Picker ────────────────────────────────────────────────────── */
270
+
271
+ .tb-variable-picker {
272
+ /* z-index handled by Tailwind utility classes */
273
+ }
274
+
275
+ /* --- Query Form dialog inputs --- */
276
+ .tb-query-form input.tb-input,
277
+ .tb-query-form select.tb-input {
278
+ height: 30px;
279
+ line-height: 30px;
280
+ font-size: 12px;
281
+ border-radius: 6px;
282
+ padding: 0 8px;
283
+ box-sizing: border-box;
284
+ }
285
+
286
+ .tb-query-form select.tb-input {
287
+ padding-right: 4px;
288
+ }
289
+
290
+ /* Fixed-width selects inside the query form condition / sort rows */
291
+ .tb-select-operator {
292
+ width: 130px;
293
+ }
294
+
295
+ .tb-select-direction {
296
+ width: 120px;
297
+ }
@@ -1,4 +1,4 @@
1
- const currencies = [
1
+ export const currencies = [
2
2
  {
3
3
  iso2: 'AW',
4
4
  name: 'Aruba',
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/ember-ui/components/template-builder/canvas';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/ember-ui/components/template-builder/element-renderer';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/ember-ui/components/template-builder/layers-panel';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/ember-ui/components/template-builder/properties-panel/field';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/ember-ui/components/template-builder/properties-panel/section';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/ember-ui/components/template-builder/properties-panel';