@fleetbase/ember-ui 0.3.12 → 0.3.14

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.
@@ -167,11 +167,17 @@ export default class ActivityLogComponent extends Component {
167
167
 
168
168
  if (c.from !== 'null' && c.from !== undefined && c.from !== '' && c.from !== c.to) {
169
169
  parts.push(
170
- `<span class="activity-change">changed <span class="activity-change-prop highlight-gray ${this.args.activityChangePropClass ?? ''}">${k}</span> from <span class="activity-change-prop highlight-gray ${this.args.activityPreviousValueClass ?? ''}">${this.#code(c.from)}</span> to <span class="activity-change-prop highlight-blue ${this.args.activityNewValueClass ?? ''}">${this.#code(c.to)}</span></span>`
170
+ `<span class="activity-change">changed <span class="activity-change-prop highlight-gray ${
171
+ this.args.activityChangePropClass ?? ''
172
+ }">${k}</span> from <span class="activity-change-prop highlight-gray ${this.args.activityPreviousValueClass ?? ''}">${this.#code(
173
+ c.from
174
+ )}</span> to <span class="activity-change-prop highlight-blue ${this.args.activityNewValueClass ?? ''}">${this.#code(c.to)}</span></span>`
171
175
  );
172
176
  } else {
173
177
  parts.push(
174
- `<span class="activity-change">set <span class="activity-change-prop highlight-gray ${this.args.activityChangePropClass ?? ''}">${k}</span> to <span class="activity-change-prop highlight-blue ${this.args.activityNewValueClass ?? ''}">${this.#code(c.to)}</span></span>`
178
+ `<span class="activity-change">set <span class="activity-change-prop highlight-gray ${
179
+ this.args.activityChangePropClass ?? ''
180
+ }">${k}</span> to <span class="activity-change-prop highlight-blue ${this.args.activityNewValueClass ?? ''}">${this.#code(c.to)}</span></span>`
175
181
  );
176
182
  }
177
183
  }
@@ -1,4 +1,4 @@
1
- <div class="ui-chart relative">
1
+ <div class="ui-chart relative {{@wrapperClass}}">
2
2
  {{#if this.isLoading}}
3
3
  <div class="overloader overloader-opacity-2">
4
4
  <div class="p-8">
@@ -1,4 +1,5 @@
1
1
  <ModelSelect
2
+ @multiple={{true}}
2
3
  @modelName={{@modelName}}
3
4
  @selectedModel={{@selectedModel}}
4
5
  @optionLabel={{@optionLabel}}
@@ -16,8 +17,6 @@
16
17
  @totalPagesParam={{@totalPagesParam}}
17
18
  @onCreate={{@onCreate}}
18
19
  @onChange={{this.change}}
19
- @searchField={{@optionLabel}}
20
- @triggerClass="ember-model-select-multiple-trigger {{@triggerClass}}"
21
20
  @triggerRole={{@triggerRole}}
22
21
  @ariaDescribedBy={{@ariaDescribedBy}}
23
22
  @ariaInvalid={{@ariaInvalid}}
@@ -48,22 +47,25 @@
48
47
  @onKeydown={{this.handleKeydown}}
49
48
  @onOpen={{this.handleOpen}}
50
49
  @options={{@options}}
51
- @optionsComponent={{@optionsComponent}}
50
+ @optionsComponent={{ensure-safe-component @optionsComponent}}
52
51
  @placeholder={{@placeholder}}
53
- @placeholderComponent={{@placeholderComponent}}
52
+ @placeholderComponent={{ensure-safe-component @placeholderComponent}}
54
53
  @preventScroll={{@preventScroll}}
55
54
  @registerAPI={{@registerAPI}}
56
55
  @renderInPlace={{@renderInPlace}}
57
56
  @required={{@required}}
58
57
  @scrollTo={{@scrollTo}}
59
58
  @search={{@search}}
60
- @searchEnabled={{@searchEnabled}}
59
+ @searchEnabled={{if (eq @searchEnabled false) false true}}
60
+ @searchField={{or @optionLabel @searchField}}
61
+ @searchFieldPosition={{or @searchFieldPosition "trigger"}}
61
62
  @searchMessage={{@searchMessage}}
62
63
  @searchPlaceholder={{@searchPlaceholder}}
63
- @selectedItemComponent={{@selectedItemComponent}}
64
+ @selectedItemComponent={{ensure-safe-component @selectedItemComponent}}
64
65
  @eventType={{@eventType}}
65
66
  @title={{@title}}
66
- @triggerComponent={{component (or @triggerComponent "power-select-multiple/trigger") tabindex=@tabindex}}
67
+ @triggerClass="ember-power-select-multiple-trigger {{@triggerClass}}"
68
+ @triggerComponent={{if @triggerComponent (component (ensure-safe-component @triggerComponent) tabindex=@tabindex) (component "power-select-multiple/trigger" tabindex=@tabindex)}}
67
69
  @triggerId={{@triggerId}}
68
70
  @verticalPosition={{@verticalPosition}}
69
71
  @tabindex={{this.computedTabIndex}}
@@ -22,6 +22,7 @@
22
22
  @initiallyOpened={{@initiallyOpened}}
23
23
  @loadingMessage={{@loadingMessage}}
24
24
  @eventType={{@eventType}}
25
+ @multiple={{@multiple}}
25
26
  @matcher={{@matcher}}
26
27
  @matchTriggerWidth={{@matchTriggerWidth}}
27
28
  @noMatchesMessage={{@noMatchesMessage}}
@@ -42,6 +43,7 @@
42
43
  @search={{perform this.searchModels}}
43
44
  @searchEnabled={{get-default-value @searchEnabled true}}
44
45
  @searchField={{@searchField}}
46
+ @searchFieldPosition={{@searchFieldPosition}}
45
47
  @searchMessage={{@searchMessage}}
46
48
  @searchPlaceholder={{@searchPlaceholder}}
47
49
  @selected={{this.selectedModel}}
@@ -16,4 +16,4 @@
16
16
  </span>
17
17
  <Input @type="tel" @value={{@value}} class="form-input flex-1 rounded-l-none" {{did-insert this.autoNumerize}} ...attributes />
18
18
  </div>
19
- </div>
19
+ </div>
@@ -2,7 +2,6 @@ import Component from '@glimmer/component';
2
2
  import { tracked } from '@glimmer/tracking';
3
3
  import { inject as service } from '@ember/service';
4
4
  import { action } from '@ember/object';
5
- import { later } from '@ember/runloop';
6
5
  import { isNone } from '@ember/utils';
7
6
  import numbersOnly from '../utils/numbers-only';
8
7
  import getCurrency from '../utils/get-currency';
@@ -12,7 +11,6 @@ export default class MoneyInputComponent extends Component {
12
11
  @service fetch;
13
12
  @service currentUser;
14
13
  @tracked currencies = getCurrency();
15
- @tracked value;
16
14
  @tracked currency;
17
15
  @tracked currencyData;
18
16
  @tracked autonumeric;
@@ -22,7 +20,6 @@ export default class MoneyInputComponent extends Component {
22
20
 
23
21
  let whois = this.currentUser.getOption('whois');
24
22
 
25
- this.value = this.args.value ?? 0;
26
23
  this.currency = this.args.currency ?? whois?.currency?.code ?? 'USD';
27
24
  this.currencyData = getCurrency(this.currency);
28
25
  }
@@ -30,7 +27,11 @@ export default class MoneyInputComponent extends Component {
30
27
  @action autoNumerize(element) {
31
28
  const { onCurrencyChange } = this.args;
32
29
  let currency = this.currencyData;
33
- let value = numbersOnly(this.value);
30
+ let value = numbersOnly(this.args.value ?? 0);
31
+
32
+ // CRITICAL: Conditional division based on currency precision
33
+ // - Currencies with decimals (precision > 0): divide by 100 (stored in cents)
34
+ // - Currencies without decimals (precision = 0): use as-is (stored in main unit)
34
35
  let amount = !currency.decimalSeparator ? value : value / 100;
35
36
 
36
37
  this.autonumeric = new AutoNumeric(element, amount, this.getCurrencyFormatOptions(currency));
@@ -40,14 +41,27 @@ export default class MoneyInputComponent extends Component {
40
41
  onCurrencyChange(currency.code, currency);
41
42
  }
42
43
 
43
- element.addEventListener('autoNumeric:formatted', this.onFormatCompleted.bind(this));
44
+ // Use rawValueModified for better change detection
45
+ element.addEventListener('autoNumeric:rawValueModified', ({ detail }) => {
46
+ if (typeof this.args.onChange === 'function') {
47
+ // Convert back to storage format
48
+ let rawValue = detail.newRawValue;
49
+ // For precision > 0: multiply by 100 to get cents
50
+ // For precision = 0: use as-is (main unit)
51
+ let storedValue = !currency.decimalSeparator ? rawValue : Math.round(rawValue * 100);
52
+ this.args.onChange(storedValue, detail);
53
+ }
54
+ });
44
55
  }
45
56
 
46
57
  @action setCurrency(currency) {
47
58
  const { onCurrencyChange } = this.args;
48
59
 
49
60
  if (this.autonumeric) {
50
- this.autonumeric.set(numbersOnly(this.value, true), this.getCurrencyFormatOptions(currency));
61
+ let value = this.autonumeric.getNumber();
62
+ this.autonumeric.update(this.getCurrencyFormatOptions(currency));
63
+ // Re-set the value to ensure it's formatted correctly with new currency
64
+ this.autonumeric.set(value);
51
65
  }
52
66
 
53
67
  this.currency = currency.code;
@@ -58,25 +72,6 @@ export default class MoneyInputComponent extends Component {
58
72
  }
59
73
  }
60
74
 
61
- @action onFormatCompleted({ detail }) {
62
- const { onFormatCompleted, onChange } = this.args;
63
-
64
- // 300ms for format to apply to input ?
65
- later(
66
- this,
67
- () => {
68
- if (typeof onFormatCompleted === 'function') {
69
- onFormatCompleted(detail);
70
- }
71
- },
72
- 300
73
- );
74
-
75
- if (typeof onChange === 'function') {
76
- onChange(detail);
77
- }
78
- }
79
-
80
75
  @action getCurrencyFormatOptions(currency) {
81
76
  let options = {
82
77
  currencySymbol: isNone(currency.symbol) ? '$' : currency.symbol,
@@ -40,10 +40,12 @@ body.fleetbase-console .ember-basic-dropdown-content {
40
40
  background-color: transparent;
41
41
  }
42
42
 
43
+ .ember-power-select-multiple-option .hide-from-trigger,
43
44
  .ember-power-select-selected-item .hide-from-trigger {
44
45
  display: none;
45
46
  }
46
47
 
48
+ .ember-power-select-multiple-option div.normalize-in-trigger,
47
49
  .ember-power-select-selected-item div.normalize-in-trigger {
48
50
  font-weight: normal;
49
51
  }
@@ -51,9 +51,23 @@
51
51
  .ember-power-select-trigger-multiple-input,
52
52
  .ember-power-select-trigger-multiple-input[type='search'] {
53
53
  @apply bg-transparent text-sm text-white outline-0 leading-5 px-1;
54
- max-height: 21px;
54
+ height: 26.42px; /** don't ask */
55
+ max-height: 40px;
55
56
  }
56
57
 
57
- .ember-power-select-option[aria-selected="true"] {
58
+ .fleetbase-console.ember-power-select-trigger-multiple-input::placeholder,
59
+ .ember-power-select-trigger-multiple-input .ember-power-select-trigger-multiple-input::placeholder {
60
+ color: #6b7280;
61
+ opacity: 1;
62
+ }
63
+
64
+ .ember-power-select-option[aria-selected='true'] {
58
65
  @apply dark:bg-gray-900 bg-gray-200;
59
- }
66
+ }
67
+
68
+ .ember-model-select-multiple-trigger > .ember-power-select-multiple-options > li.ember-power-select-multiple-option {
69
+ display: flex;
70
+ align-items: center;
71
+ padding: 0.25rem 0.5rem;
72
+ border-radius: 0.45rem;
73
+ }
package/index.js CHANGED
@@ -21,7 +21,7 @@ const postcssOptions = {
21
21
  plugins: [
22
22
  postcssAtRulesVariables,
23
23
  postcssImport({
24
- path: ['node_modules'],
24
+ path: ['node_modules', path.join(__dirname, 'addon/styles')],
25
25
  plugins: [postcssAtRulesVariables, postcssImport],
26
26
  }),
27
27
  postcssMixins,
@@ -55,13 +55,43 @@ module.exports = {
55
55
  postcssOptions,
56
56
  },
57
57
 
58
+ treeForStyles: function () {
59
+ // Only provide styles to the root application, not to engines
60
+ // This prevents engines from trying to compile ember-ui styles
61
+ let parent = this.parent;
62
+ while (parent) {
63
+ const isEngine = parent.lazyLoading === true || (parent.lazyLoading && parent.lazyLoading.enabled === true);
64
+ if (isEngine) {
65
+ // Parent is an engine - don't provide styles
66
+ return null;
67
+ }
68
+ parent = parent.parent;
69
+ }
70
+
71
+ // Parent is the root app - provide styles normally
72
+ return this._super.treeForStyles ? this._super.treeForStyles.apply(this, arguments) : null;
73
+ },
74
+
58
75
  included: function (app) {
59
76
  this._super.included.apply(this, arguments);
60
77
 
61
- // Get Application Host
78
+ // Check if we're being included by an engine
79
+ // If so, skip setting postcssOptions to prevent engines from trying to compile our styles
80
+ let parent = this.parent;
81
+ while (parent) {
82
+ const isEngine = parent.lazyLoading === true || (parent.lazyLoading && parent.lazyLoading.enabled === true);
83
+ if (isEngine) {
84
+ // We're in an engine - don't set postcssOptions
85
+ // The engine will inherit from the host app
86
+ return;
87
+ }
88
+ parent = parent.parent;
89
+ }
90
+
91
+ // Get Application Host (skips engines, finds root app)
62
92
  app = this.findApplicationHost(app);
63
93
 
64
- // PostCSS Options
94
+ // PostCSS Options - only applied to the root application
65
95
  app.options = app.options || {};
66
96
  app.options.postcssOptions = postcssOptions;
67
97
 
@@ -128,11 +158,11 @@ module.exports = {
128
158
  findApplicationHost(app) {
129
159
  let current = this;
130
160
  do {
131
- if (current.lazyLoading === true || (current.lazyLoading && current.lazyLoading.enabled === true)) {
132
- app = current;
133
- break;
161
+ // Skip engines - we want the root application, not an engine
162
+ const isEngine = current.lazyLoading === true || (current.lazyLoading && current.lazyLoading.enabled === true);
163
+ if (!isEngine) {
164
+ app = current.app || app;
134
165
  }
135
- app = current.app || app;
136
166
  } while (current.parent.parent && (current = current.parent));
137
167
 
138
168
  return app;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fleetbase/ember-ui",
3
- "version": "0.3.12",
3
+ "version": "0.3.14",
4
4
  "description": "Fleetbase UI provides all the interface components, helpers, services and utilities for building a Fleetbase extension into the Console.",
5
5
  "keywords": [
6
6
  "fleetbase-ui",
@@ -127,6 +127,7 @@
127
127
  "broccoli-asset-rev": "^3.0.0",
128
128
  "broccoli-funnel": "^3.0.8",
129
129
  "broccoli-merge-trees": "^4.2.0",
130
+ "broccoli-postcss-single": "^5.0.2",
130
131
  "clean-css": "^5.3.2",
131
132
  "concurrently": "^8.2.2",
132
133
  "ember-cli": "~5.4.1",
@@ -4,6 +4,7 @@ module.exports = {
4
4
  content: [
5
5
  './app/**/*.{hbs,js}',
6
6
  './addon/**/*.{hbs,js}',
7
+ './addon/**/*.css',
7
8
  // All Fleetbase packages (both pnpm symlinked and normal installs)
8
9
  './node_modules/@fleetbase+*/**/addon/**/*.{hbs,js}',
9
10
  './node_modules/@fleetbase/**/addon/**/*.{hbs,js}',