@kumori/aurora-wui-components 0.0.306-dev4506.1 → 0.0.306-dev4506.2

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.
@@ -0,0 +1,15 @@
1
+ export interface TypedNumericText {
2
+ text: string;
3
+ value: string;
4
+ caret: number;
5
+ }
6
+ export interface TypedNumericOptions {
7
+ integerOnly: boolean;
8
+ max: number;
9
+ }
10
+ export declare function toNumber(text: unknown): number | null;
11
+ export declare function formatNumericText(raw: string): string;
12
+ export declare function formatNumericValue(value: unknown): string;
13
+ export declare function sanitizeNumericText(text: string, integerOnly: boolean): string;
14
+ export declare function processTypedText(typed: string, caret: number, options: TypedNumericOptions): TypedNumericText;
15
+ //# sourceMappingURL=axebow-numeric-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"axebow-numeric-format.d.ts","sourceRoot":"","sources":["../../../src/components/axebow-input/axebow-numeric-format.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,OAAO,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAKrD;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAQrD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAOzD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,MAAM,CAS9E;AAeD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,gBAAgB,CAM7G"}
@@ -11,8 +11,11 @@ export declare class AxebowNumericInput extends AxebowInputBase {
11
11
  stepAmount: number;
12
12
  fixedField: boolean;
13
13
  minWidth?: string;
14
+ private _text;
15
+ willUpdate(changed: PropertyValues): void;
14
16
  updated(changed: PropertyValues): void;
15
17
  protected handleChange(e: Event): void;
18
+ private _emitValue;
16
19
  protected handleKeyDown(e: KeyboardEvent): void;
17
20
  private _bumpValue;
18
21
  private _renderStepper;
@@ -1 +1 @@
1
- {"version":3,"file":"axebow-numeric-input.d.ts","sourceRoot":"","sources":["../../../src/components/axebow-input/axebow-numeric-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,cAAc,EAAE,MAAM,KAAK,CAAC;AAGhD,OAAO,yDAAyD,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,qBACa,kBAAmB,SAAQ,eAAe;IACrD,MAAM,CAAC,MAAM,4BAqEX;IAE0B,GAAG,SAA2B;IAC9B,GAAG,SAAK;IACP,WAAW,UAAS;IAErB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,UAAQ;IACpB,UAAU,SAAK;IACd,UAAU,UAAS;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAE9C,OAAO,CAAC,OAAO,EAAE,cAAc;IAkC/B,SAAS,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK;IAgB/B,SAAS,CAAC,aAAa,CAAC,CAAC,EAAE,aAAa;IAMxC,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,cAAc;IA2BtB,MAAM;CAqBP"}
1
+ {"version":3,"file":"axebow-numeric-input.d.ts","sourceRoot":"","sources":["../../../src/components/axebow-input/axebow-numeric-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,cAAc,EAAE,MAAM,KAAK,CAAC;AAGhD,OAAO,yDAAyD,CAAC;AAEjE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,qBACa,kBAAmB,SAAQ,eAAe;IACrD,MAAM,CAAC,MAAM,4BA6DX;IAE0B,GAAG,SAA2B;IAC9B,GAAG,SAAK;IACP,WAAW,UAAS;IAErB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,UAAQ;IACpB,UAAU,SAAK;IACd,UAAU,UAAS;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAErC,OAAO,CAAC,KAAK,CAAM;IAE5B,UAAU,CAAC,OAAO,EAAE,cAAc;IAOlC,OAAO,CAAC,OAAO,EAAE,cAAc;IAkC/B,SAAS,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK;IAkB/B,OAAO,CAAC,UAAU;IAOlB,SAAS,CAAC,aAAa,CAAC,CAAC,EAAE,aAAa;IASxC,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,cAAc;IA2BtB,MAAM;CAsBP"}
package/dist/index.js CHANGED
@@ -30,6 +30,7 @@ var axebowTheme = css`
30
30
  :host, .theme {
31
31
  --axebow-primary: var(--color-primary, #34495e);
32
32
  --axebow-primary-light: var(--color-primary-light, #b4cded);
33
+ --axebow-indigo-blue: var(--color-indigo-blue, #344966);
33
34
  --axebow-tertiary: var(--color-tertiary, #006bff);
34
35
  --axebow-success: var(--color-success, #0ecd9a);
35
36
  --axebow-secondary: var(--color-secondary, #78787a);
@@ -2514,6 +2515,68 @@ var AxebowTextInput = class AxebowTextInput extends AxebowInputBase {
2514
2515
  };
2515
2516
  AxebowTextInput = __decorate([customElement("axebow-text-input")], AxebowTextInput);
2516
2517
  //#endregion
2518
+ //#region src/components/axebow-input/axebow-numeric-format.ts
2519
+ var DECIMAL_SEPARATOR = ".";
2520
+ var THOUSANDS_SEPARATOR = ",";
2521
+ var NEGATIVE_SIGN = "-";
2522
+ var SIGNIFICANT_CHARACTER = /[\d.-]/;
2523
+ function toNumber(text) {
2524
+ const normalized = String(text ?? "").replace(/,/g, "").trim();
2525
+ if (normalized === "") return null;
2526
+ const parsed = Number(normalized);
2527
+ return Number.isFinite(parsed) ? parsed : null;
2528
+ }
2529
+ function formatNumericText(raw) {
2530
+ const negative = raw.startsWith(NEGATIVE_SIGN);
2531
+ const unsigned = negative ? raw.slice(1) : raw;
2532
+ const separatorIndex = unsigned.indexOf(DECIMAL_SEPARATOR);
2533
+ const integerPart = separatorIndex === -1 ? unsigned : unsigned.slice(0, separatorIndex);
2534
+ const fractionPart = separatorIndex === -1 ? "" : unsigned.slice(separatorIndex);
2535
+ const grouped = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, THOUSANDS_SEPARATOR);
2536
+ return `${negative ? NEGATIVE_SIGN : ""}${grouped}${fractionPart}`;
2537
+ }
2538
+ function formatNumericValue(value) {
2539
+ const text = String(value ?? "").trim();
2540
+ if (text === "") return "";
2541
+ if (/^-?\d*\.?\d*$/.test(text)) return formatNumericText(text);
2542
+ const parsed = toNumber(text);
2543
+ if (parsed === null) return "";
2544
+ return formatNumericText(parsed.toLocaleString("en-US", {
2545
+ useGrouping: false,
2546
+ maximumFractionDigits: 20
2547
+ }));
2548
+ }
2549
+ function sanitizeNumericText(text, integerOnly) {
2550
+ const negative = text.trim().startsWith(NEGATIVE_SIGN);
2551
+ const cleaned = text.replace(/[^\d.]/g, "");
2552
+ const separatorIndex = cleaned.indexOf(DECIMAL_SEPARATOR);
2553
+ const integerPart = (separatorIndex === -1 ? cleaned : cleaned.slice(0, separatorIndex)).replace(/^0+(?=\d)/, "");
2554
+ const fractionDigits = separatorIndex === -1 ? "" : cleaned.slice(separatorIndex + 1).replace(/\./g, "");
2555
+ const body = integerOnly || separatorIndex === -1 ? integerPart : `${integerPart}${DECIMAL_SEPARATOR}${fractionDigits}`;
2556
+ return `${negative ? NEGATIVE_SIGN : ""}${body}`;
2557
+ }
2558
+ function caretInText(typed, caret, text) {
2559
+ const significantBefore = Array.from(typed.slice(0, caret)).filter((character) => SIGNIFICANT_CHARACTER.test(character)).length;
2560
+ let position = 0;
2561
+ let seen = 0;
2562
+ while (position < text.length && seen < significantBefore) {
2563
+ if (SIGNIFICANT_CHARACTER.test(text[position])) seen++;
2564
+ position++;
2565
+ }
2566
+ return position;
2567
+ }
2568
+ function processTypedText(typed, caret, options) {
2569
+ let raw = sanitizeNumericText(typed, options.integerOnly);
2570
+ const parsed = toNumber(raw);
2571
+ if (options.integerOnly && parsed !== null && parsed > options.max) raw = String(options.max);
2572
+ const text = formatNumericText(raw);
2573
+ return {
2574
+ text,
2575
+ value: toNumber(raw) === null ? "" : raw,
2576
+ caret: caretInText(typed, caret, text)
2577
+ };
2578
+ }
2579
+ //#endregion
2517
2580
  //#region src/components/axebow-input/axebow-numeric-input.ts
2518
2581
  var AxebowNumericInput = class AxebowNumericInput extends AxebowInputBase {
2519
2582
  constructor(..._args) {
@@ -2524,6 +2587,7 @@ var AxebowNumericInput = class AxebowNumericInput extends AxebowInputBase {
2524
2587
  this.showStepper = true;
2525
2588
  this.stepAmount = 1;
2526
2589
  this.fixedField = false;
2590
+ this._text = "";
2527
2591
  }
2528
2592
  static {
2529
2593
  this.styles = [...AxebowInputBase.baseStyles, css`
@@ -2531,14 +2595,6 @@ var AxebowNumericInput = class AxebowNumericInput extends AxebowInputBase {
2531
2595
  display: block;
2532
2596
  width: 100%;
2533
2597
  }
2534
- sl-input::part(input)::-webkit-outer-spin-button,
2535
- sl-input::part(input)::-webkit-inner-spin-button {
2536
- -webkit-appearance: none;
2537
- margin: 0;
2538
- }
2539
- sl-input::part(input) {
2540
- -moz-appearance: textfield;
2541
- }
2542
2598
  :host(.axebow-fixed-width) sl-input {
2543
2599
  width: var(--axebow-input-width) !important;
2544
2600
  }
@@ -2594,6 +2650,10 @@ var AxebowNumericInput = class AxebowNumericInput extends AxebowInputBase {
2594
2650
  }
2595
2651
  `];
2596
2652
  }
2653
+ willUpdate(changed) {
2654
+ super.willUpdate(changed);
2655
+ if (changed.has("value") && toNumber(this.value) !== toNumber(this._text)) this._text = formatNumericValue(this.value);
2656
+ }
2597
2657
  updated(changed) {
2598
2658
  super.updated(changed);
2599
2659
  if (changed.has("fixedWidth")) if (this.fixedWidth) {
@@ -2621,28 +2681,43 @@ var AxebowNumericInput = class AxebowNumericInput extends AxebowInputBase {
2621
2681
  }
2622
2682
  handleChange(e) {
2623
2683
  if (this.disabled) return;
2624
- if (this.integerOnly) {
2625
- const target = e.target;
2626
- let truncated = Math.trunc(Number(target.value));
2627
- if (truncated > this.max) truncated = this.max;
2628
- target.value = truncated.toString();
2629
- this.value = target.value;
2630
- this.callback?.(e);
2631
- return;
2684
+ const input = e.target;
2685
+ const typed = input.value;
2686
+ const { text, value, caret } = processTypedText(typed, input.input?.selectionStart ?? typed.length, {
2687
+ integerOnly: this.integerOnly,
2688
+ max: this.max
2689
+ });
2690
+ if (text !== typed) {
2691
+ const hasFocus = input.shadowRoot?.activeElement === input.input;
2692
+ input.value = text;
2693
+ if (hasFocus) input.updateComplete.then(() => input.setSelectionRange(caret, caret));
2632
2694
  }
2633
- super.handleChange(e);
2695
+ this._text = text;
2696
+ this.value = value;
2697
+ this._emitValue(value);
2698
+ }
2699
+ _emitValue(value) {
2700
+ const source = document.createElement("input");
2701
+ source.value = value;
2702
+ source.addEventListener("input", (event) => this.callback?.(event), { once: true });
2703
+ source.dispatchEvent(new Event("input"));
2634
2704
  }
2635
2705
  handleKeyDown(e) {
2636
- if (this.integerOnly && (e.key === "." || e.key === "," || e.key === "e" || e.key === "E")) e.preventDefault();
2706
+ if (e.key === "ArrowUp" || e.key === "ArrowDown") {
2707
+ e.preventDefault();
2708
+ this._bumpValue(e.key === "ArrowUp" ? 1 : -1);
2709
+ return;
2710
+ }
2711
+ if (this.integerOnly && e.key === ".") e.preventDefault();
2637
2712
  }
2638
2713
  _bumpValue(sign) {
2639
2714
  if (this.disabled) return;
2640
2715
  const step = this.integerOnly ? Math.trunc(this.stepAmount) || 1 : this.stepAmount;
2641
- const current = Number(this.value) || 0;
2716
+ const current = toNumber(this.value) ?? 0;
2642
2717
  const next = Math.min(this.max, Math.max(this.min, current + sign * step));
2643
2718
  const input = this.renderRoot.querySelector("sl-input");
2644
2719
  if (!input) return;
2645
- input.value = next.toString();
2720
+ input.value = formatNumericValue(next);
2646
2721
  input.dispatchEvent(new Event("sl-input", {
2647
2722
  bubbles: true,
2648
2723
  composed: true
@@ -2650,7 +2725,7 @@ var AxebowNumericInput = class AxebowNumericInput extends AxebowInputBase {
2650
2725
  }
2651
2726
  _renderStepper() {
2652
2727
  if (!this.showStepper) return "";
2653
- const current = Number(this.value) || 0;
2728
+ const current = toNumber(this.value) ?? 0;
2654
2729
  return html`
2655
2730
  <div slot="suffix" class="axebow-numeric-stepper">
2656
2731
  <button
@@ -2678,15 +2753,16 @@ var AxebowNumericInput = class AxebowNumericInput extends AxebowInputBase {
2678
2753
  const content = html`
2679
2754
  <div class="${this.hasError ? "input-error" : ""}">
2680
2755
  <sl-input
2681
- type="number"
2756
+ type="text"
2757
+ inputmode="${this.integerOnly ? "numeric" : "decimal"}"
2758
+ autocomplete="off"
2682
2759
  placeholder="${this.placeholder}"
2683
2760
  @sl-input="${this.handleChange}"
2684
2761
  @keydown="${this.handleKeyDown}"
2685
- .value="${live(this.value)}"
2762
+ .value="${live(this._text)}"
2686
2763
  ?disabled="${this.disabled}"
2687
2764
  max=${this.max}
2688
2765
  min=${this.min}
2689
- step=${this.integerOnly ? "1" : "any"}
2690
2766
  >
2691
2767
  ${this._renderStepper()}
2692
2768
  </sl-input>
@@ -2704,6 +2780,7 @@ __decorate([property({ type: Boolean })], AxebowNumericInput.prototype, "showSte
2704
2780
  __decorate([property({ type: Number })], AxebowNumericInput.prototype, "stepAmount", void 0);
2705
2781
  __decorate([property({ type: Boolean })], AxebowNumericInput.prototype, "fixedField", void 0);
2706
2782
  __decorate([property({ type: String })], AxebowNumericInput.prototype, "minWidth", void 0);
2783
+ __decorate([state()], AxebowNumericInput.prototype, "_text", void 0);
2707
2784
  AxebowNumericInput = __decorate([customElement("axebow-numeric-input")], AxebowNumericInput);
2708
2785
  //#endregion
2709
2786
  //#region src/components/axebow-input/axebow-checkbox-input.ts