@ng-forge/dynamic-forms-bootstrap 0.10.0-next.1 → 0.10.0-next.3

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.
@@ -10,8 +10,7 @@ import { explicitEffect } from 'ngxtension/explicit-effect';
10
10
  class BsButtonFieldComponent {
11
11
  action = injectNgForgeAction();
12
12
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
13
- /** Resolved button type defaults to 'button' unless overridden via props. */
14
- buttonType = computed(() => this.props()?.type ?? 'button', ...(ngDevMode ? [{ debugName: "buttonType" }] : /* istanbul ignore next */ []));
13
+ buttonType = computed(() => this.props()?.type ?? 'button', ...(ngDevMode ? [{ debugName: "buttonType" }] : /* istanbul ignore next */ []));
15
14
  buttonTestId = computed(() => `${this.buttonType()}-${this.action.key()}`, ...(ngDevMode ? [{ debugName: "buttonTestId" }] : /* istanbul ignore next */ []));
16
15
  buttonClasses = computed(() => {
17
16
  const p = this.props();
@@ -29,8 +28,7 @@ class BsButtonFieldComponent {
29
28
  .filter(Boolean)
30
29
  .join(' ');
31
30
  }, ...(ngDevMode ? [{ debugName: "buttonClasses" }] : /* istanbul ignore next */ []));
32
- /** Submit buttons let the native form handle submission; other buttons dispatch via the directive. */
33
- onClick() {
31
+ onClick() {
34
32
  if (this.buttonType() === 'submit')
35
33
  return;
36
34
  this.action.dispatch();
@@ -74,7 +72,6 @@ var bsButton_component = /*#__PURE__*/Object.freeze({
74
72
  default: BsButtonFieldComponent
75
73
  });
76
74
 
77
- // Public API - component
78
75
 
79
76
  class BsCheckboxFieldComponent {
80
77
  ngf = injectNgForgeField();
@@ -152,9 +149,6 @@ var bsCheckbox_component = /*#__PURE__*/Object.freeze({
152
149
  default: BsCheckboxFieldComponent
153
150
  });
154
151
 
155
- /**
156
- * Directive to set min, max, and step attributes on form inputs
157
- */
158
152
  class InputConstraintsDirective {
159
153
  dfMin = input(...(ngDevMode ? [undefined, { debugName: "dfMin" }] : /* istanbul ignore next */ []));
160
154
  dfMax = input(...(ngDevMode ? [undefined, { debugName: "dfMax" }] : /* istanbul ignore next */ []));
@@ -203,8 +197,7 @@ class BsDatepickerFieldComponent {
203
197
  maxDate = input(null, ...(ngDevMode ? [{ debugName: "maxDate" }] : /* istanbul ignore next */ []));
204
198
  startAt = input(null, ...(ngDevMode ? [{ debugName: "startAt" }] : /* istanbul ignore next */ []));
205
199
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
206
- // Helper methods to convert Date to string for HTML attributes
207
- minAsString = computed(() => {
200
+ minAsString = computed(() => {
208
201
  const min = this.minDate();
209
202
  return min instanceof Date ? min.toISOString().split('T')[0] : min;
210
203
  }, ...(ngDevMode ? [{ debugName: "minAsString" }] : /* istanbul ignore next */ []));
@@ -363,45 +356,12 @@ var bsDatepicker_component = /*#__PURE__*/Object.freeze({
363
356
  default: BsDatepickerFieldComponent
364
357
  });
365
358
 
366
- /**
367
- * Injection token for Bootstrap form configuration.
368
- * Use this to provide global configuration for Bootstrap form fields.
369
- *
370
- * @example
371
- * ```typescript
372
- * import { provideDynamicForm } from '@ng-forge/dynamic-forms';
373
- * import { withBootstrapFields } from '@ng-forge/dynamic-forms-bootstrap';
374
- *
375
- * export const appConfig: ApplicationConfig = {
376
- * providers: [
377
- * provideDynamicForm(
378
- * ...withBootstrapFields({
379
- * floatingLabel: true,
380
- * size: 'lg'
381
- * })
382
- * )
383
- * ]
384
- * };
385
- * ```
386
- */
387
359
  const BOOTSTRAP_CONFIG = new InjectionToken('BOOTSTRAP_CONFIG');
388
360
 
389
- /** Bootstrap adapter binding for the shared preset runner. */
390
361
  function runBsPresetAction(preset, ctx, collaborators) {
391
362
  return runPresetAction(preset, ctx, collaborators, 'Bootstrap', 'bs-input');
392
363
  }
393
364
 
394
- /**
395
- * Per-field writable signal that overrides the input's `type` attribute.
396
- *
397
- * Provided at the `bs-input` field component level. The button addon's
398
- * `'toggle-password-visibility'` preset writes to it; the field component
399
- * reads it to compute its effective `type`.
400
- *
401
- * Optional from a button's perspective — when the button is hosted inside a
402
- * field that doesn't provide this token (e.g., textarea or a future
403
- * non-input field), the toggle preset is a no-op.
404
- */
405
365
  const BS_INPUT_TYPE_OVERRIDE = new InjectionToken('BS_INPUT_TYPE_OVERRIDE');
406
366
 
407
367
  class BsInputFieldComponent {
@@ -409,18 +369,11 @@ class BsInputFieldComponent {
409
369
  ngf = injectNgForgeField();
410
370
  ngfa = injectNgForgeAddons();
411
371
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
412
- /**
413
- * Wrapper-style host bag pushed by `DfFieldOutlet`. Declared at the
414
- * component level so `setInputIfDeclared` (which uses
415
- * `reflectComponentType`) can write it.
416
- */
417
- fieldInputs = input(...(ngDevMode ? [undefined, { debugName: "fieldInputs" }] : /* istanbul ignore next */ []));
418
- /** Per-instance type override populated by `toggle-password-visibility` preset. */
419
- typeOverride = inject(BS_INPUT_TYPE_OVERRIDE);
372
+ fieldInputs = input(...(ngDevMode ? [undefined, { debugName: "fieldInputs" }] : /* istanbul ignore next */ []));
373
+ typeOverride = inject(BS_INPUT_TYPE_OVERRIDE);
420
374
  size = computed(() => this.props()?.size ?? this.bootstrapConfig?.size, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
421
375
  floatingLabel = computed(() => this.props()?.floatingLabel ?? this.bootstrapConfig?.floatingLabel ?? false, ...(ngDevMode ? [{ debugName: "floatingLabel" }] : /* istanbul ignore next */ []));
422
- /** Override (set by `toggle-password-visibility` preset) wins over `props().type`. */
423
- type = computed(() => this.typeOverride() ?? this.props()?.type ?? 'text', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
376
+ type = computed(() => this.typeOverride() ?? this.props()?.type ?? 'text', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
424
377
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: BsInputFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
425
378
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: BsInputFieldComponent, isStandalone: true, selector: "df-bs-input", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, fieldInputs: { classPropertyName: "fieldInputs", publicName: "fieldInputs", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
426
379
  {
@@ -428,18 +381,12 @@ class BsInputFieldComponent {
428
381
  useFactory: () => signal(undefined),
429
382
  },
430
383
  {
431
- // Adapter-specific preset semantics for `bs-button` addons (clear /
432
- // reset / paste / copy / toggle-password-visibility). The directive
433
- // (`NgForgeAddonAction`) delegates here when an addon configures a
434
- // `preset`. Per-bs-input-instance so the `typeOverride` signal is
435
- // scoped to one field.
436
- provide: ADDON_PRESET_HANDLER,
384
+ provide: ADDON_PRESET_HANDLER,
437
385
  useFactory: () => {
438
386
  const typeOverride = inject(BS_INPUT_TYPE_OVERRIDE);
439
387
  const fsc = inject(FIELD_SIGNAL_CONTEXT, { optional: true });
440
388
  const logger = inject(DynamicFormLogger);
441
- // forwardRef for baselineType only — host.props()?.type gates toggle-password-visibility.
442
- const host = inject(forwardRef(() => BsInputFieldComponent));
389
+ const host = inject(forwardRef(() => BsInputFieldComponent));
443
390
  return {
444
391
  run: (preset, ctx) => {
445
392
  const fieldKey = ctx.field.key;
@@ -716,18 +663,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
716
663
  useFactory: () => signal(undefined),
717
664
  },
718
665
  {
719
- // Adapter-specific preset semantics for `bs-button` addons (clear /
720
- // reset / paste / copy / toggle-password-visibility). The directive
721
- // (`NgForgeAddonAction`) delegates here when an addon configures a
722
- // `preset`. Per-bs-input-instance so the `typeOverride` signal is
723
- // scoped to one field.
724
- provide: ADDON_PRESET_HANDLER,
666
+ provide: ADDON_PRESET_HANDLER,
725
667
  useFactory: () => {
726
668
  const typeOverride = inject(BS_INPUT_TYPE_OVERRIDE);
727
669
  const fsc = inject(FIELD_SIGNAL_CONTEXT, { optional: true });
728
670
  const logger = inject(DynamicFormLogger);
729
- // forwardRef for baselineType only — host.props()?.type gates toggle-password-visibility.
730
- const host = inject(forwardRef(() => BsInputFieldComponent));
671
+ const host = inject(forwardRef(() => BsInputFieldComponent));
731
672
  return {
732
673
  run: (preset, ctx) => {
733
674
  const fieldKey = ctx.field.key;
@@ -754,8 +695,7 @@ class BsMultiCheckboxFieldComponent {
754
695
  ngf = injectNgForgeField();
755
696
  options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
756
697
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
757
- /** Computed map of checked option values for O(1) lookup in template */
758
- checkedValuesMap = computed(() => {
698
+ checkedValuesMap = computed(() => {
759
699
  const map = {};
760
700
  for (const opt of this.valueViewModel()) {
761
701
  map[String(opt.value)] = true;
@@ -884,26 +824,15 @@ var bsMultiCheckbox_component = /*#__PURE__*/Object.freeze({
884
824
  default: BsMultiCheckboxFieldComponent
885
825
  });
886
826
 
887
- /**
888
- * Bootstrap radio group implementing FormValueControl. Rendered inside
889
- * `df-bs-radio` — each `<input type="radio">` carries `ngForgeControl`, so
890
- * the marker absorbs meta + aria from the ambient parent NgForgeField.
891
- */
892
827
  class BsRadioGroupComponent {
893
- // Value model - FormField directive binds form value to this
894
- value = model(undefined, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
895
- // Optional FormValueControl properties - Field directive will bind these
896
- disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
828
+ value = model(undefined, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
829
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
897
830
  readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
898
831
  name = input('', ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
899
- // Component-specific inputs
900
- label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
832
+ label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
901
833
  options = input.required(...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
902
834
  properties = input(...(ngDevMode ? [undefined, { debugName: "properties" }] : /* istanbul ignore next */ []));
903
- /**
904
- * Handle radio button change event
905
- */
906
- onRadioChange(newValue) {
835
+ onRadioChange(newValue) {
907
836
  if (!this.disabled() && !this.readonly()) {
908
837
  this.value.set(newValue);
909
838
  }
@@ -1457,12 +1386,7 @@ var bsToggle_component = /*#__PURE__*/Object.freeze({
1457
1386
  default: BsToggleFieldComponent
1458
1387
  });
1459
1388
 
1460
- // Public exports for bootstrap field components and types
1461
1389
 
1462
- /**
1463
- * Bootstrap field type constants
1464
- * Based on available field components in the /fields folder
1465
- */
1466
1390
  const BsField = {
1467
1391
  Input: 'input',
1468
1392
  Select: 'select',
@@ -1485,17 +1409,6 @@ const BsField = {
1485
1409
  Toggle: 'toggle',
1486
1410
  };
1487
1411
 
1488
- /**
1489
- * Generic button mapper for custom events or basic buttons.
1490
- * For specific button types (submit, next, prev, add/remove array items),
1491
- * use the dedicated field types and their specific mappers.
1492
- *
1493
- * Supports template property for array events (AppendArrayItemEvent, PrependArrayItemEvent, InsertArrayItemEvent)
1494
- * which enables the $template token in eventArgs.
1495
- *
1496
- * @param fieldDef The button field definition
1497
- * @returns Signal containing Record of input names to values for ngComponentOutlet
1498
- */
1499
1412
  function buttonFieldMapper(fieldDef) {
1500
1413
  const defaultProps = inject(DEFAULT_PROPS);
1501
1414
  const arrayContext = inject(ARRAY_CONTEXT, { optional: true });
@@ -1510,19 +1423,15 @@ function buttonFieldMapper(fieldDef) {
1510
1423
  if (fieldDef.hidden !== undefined) {
1511
1424
  inputs['hidden'] = fieldDef.hidden;
1512
1425
  }
1513
- // Add event binding for button events
1514
- if ('event' in fieldDef && fieldDef.event !== undefined) {
1426
+ if ('event' in fieldDef && fieldDef.event !== undefined) {
1515
1427
  inputs['event'] = fieldDef.event;
1516
1428
  }
1517
- // Add eventArgs binding if provided
1518
- if ('eventArgs' in fieldDef && fieldDef.eventArgs !== undefined) {
1429
+ if ('eventArgs' in fieldDef && fieldDef.eventArgs !== undefined) {
1519
1430
  inputs['eventArgs'] = fieldDef.eventArgs;
1520
1431
  }
1521
- // Add eventContext for token resolution (supports $template, $arrayKey, $index, etc.)
1522
- const template = 'template' in fieldDef ? fieldDef.template : undefined;
1432
+ const template = 'template' in fieldDef ? fieldDef.template : undefined;
1523
1433
  if (template || arrayContext) {
1524
- // Read signal value if index is a signal (supports differential updates)
1525
- const getIndex = () => {
1434
+ const getIndex = () => {
1526
1435
  if (!arrayContext)
1527
1436
  return -1;
1528
1437
  return isSignal(arrayContext.index) ? arrayContext.index() : arrayContext.index;
@@ -1539,12 +1448,6 @@ function buttonFieldMapper(fieldDef) {
1539
1448
  });
1540
1449
  }
1541
1450
 
1542
- /**
1543
- * Navigation button mappers for Bootstrap - re-exported from integration package.
1544
- *
1545
- * These mappers handle submit, next, and previous buttons with proper
1546
- * disabled state resolution based on form validity and options.
1547
- */
1548
1451
 
1549
1452
  const VALUE_FIELD_TYPES_BASE = {
1550
1453
  renderReadyWhen: ['field'],
@@ -1684,16 +1587,9 @@ const BOOTSTRAP_FIELD_TYPES = [
1684
1587
  },
1685
1588
  ];
1686
1589
 
1687
- /**
1688
- * Module augmentation for @ng-forge/dynamic-form
1689
- * This file augments the FieldRegistryLeaves interface to include
1690
- * all Bootstrap field types provided by this library.
1691
- */
1692
1590
 
1693
1591
  function withBootstrapFields(config) {
1694
- // Always include the addons feature — bs-icon / bs-button are part of
1695
- // the canonical Bootstrap surface.
1696
- const base = [...BOOTSTRAP_FIELD_TYPES, withBootstrapAddons()];
1592
+ const base = [...BOOTSTRAP_FIELD_TYPES, withBootstrapAddons()];
1697
1593
  if (config) {
1698
1594
  base.push({
1699
1595
  ɵkind: 'bootstrap-config',
@@ -1717,39 +1613,15 @@ const BS_BUTTON_KIND = {
1717
1613
  kind: 'bs-button',
1718
1614
  loadComponent: () => Promise.resolve().then(function () { return bsButtonAddon_component; }).then((m) => m.BsButtonAddonComponent),
1719
1615
  validate: (addon, fieldKey) => {
1720
- // Exactly one of preset / actionRef / action validator drops the addon
1721
- // (with warning) if the rule is violated.
1722
- const set = [addon.preset, addon.actionRef, addon.action].filter((v) => v !== undefined);
1616
+ const set = [addon.preset, addon.actionRef, addon.action].filter((v) => v !== undefined);
1723
1617
  if (set.length > 1) {
1724
1618
  throw new DynamicFormError(`Addon kind 'bs-button' on field '${fieldKey}' has more than one of preset/actionRef/action — exactly one allowed.`);
1725
1619
  }
1726
- // Icon-only buttons require ariaLabel for screen readers.
1727
- if (addon.icon && !addon.label && !addon.ariaLabel) {
1620
+ if (addon.icon && !addon.label && !addon.ariaLabel) {
1728
1621
  throw new DynamicFormError(`Addon kind 'bs-button' on field '${fieldKey}' is icon-only — provide 'ariaLabel' for accessibility.`);
1729
1622
  }
1730
1623
  },
1731
1624
  };
1732
- /**
1733
- * Register Bootstrap-shipped addon kinds (`bs-icon`, `bs-button`) standalone.
1734
- *
1735
- * **Most users don't need this** — `withBootstrapFields()` auto-includes
1736
- * these kinds. Call `withBootstrapAddons()` directly only when you want
1737
- * Bootstrap addon kinds without the Bootstrap field types (e.g., a custom
1738
- * field set that wants to render `bs-icon` prefixes), or when you're
1739
- * stitching addons through a different DI scope.
1740
- *
1741
- * @example
1742
- * ```typescript
1743
- * // Custom field types + Bootstrap addon kinds.
1744
- * provideDynamicForm(
1745
- * ...myCustomFields(),
1746
- * withBootstrapAddons(),
1747
- * );
1748
- * ```
1749
- *
1750
- * Adapter authors who need to override a kind with a customised renderer
1751
- * should call `withCustomAddon(...)` directly instead.
1752
- */
1753
1625
  function withBootstrapAddons() {
1754
1626
  return {
1755
1627
  ɵkind: 'addons',
@@ -1760,17 +1632,9 @@ function withBootstrapAddons() {
1760
1632
  };
1761
1633
  }
1762
1634
 
1763
- /**
1764
- * Renderer for the `bs-icon` addon kind.
1765
- *
1766
- * Outputs `<i class="bi bi-{icon}">`. The host is set `aria-hidden="true"`
1767
- * by default; if the addon supplies an `ariaLabel`, it is applied so the
1768
- * icon is announced by screen readers.
1769
- */
1770
1635
  class BsIconAddonComponent {
1771
1636
  addon = input.required(...(ngDevMode ? [{ debugName: "addon" }] : /* istanbul ignore next */ []));
1772
- /** Accepted for contract uniformity `NgComponentOutlet` setInput is strict; every kind must declare it. */
1773
- fieldInputs = input(...(ngDevMode ? [undefined, { debugName: "fieldInputs" }] : /* istanbul ignore next */ []));
1637
+ fieldInputs = input(...(ngDevMode ? [undefined, { debugName: "fieldInputs" }] : /* istanbul ignore next */ []));
1774
1638
  iconClass = computed(() => `bi bi-${this.addon().icon}`, ...(ngDevMode ? [{ debugName: "iconClass" }] : /* istanbul ignore next */ []));
1775
1639
  ariaLabel = computed(() => this.addon().ariaLabel, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
1776
1640
  hasAriaLabel = computed(() => this.addon().ariaLabel !== undefined, ...(ngDevMode ? [{ debugName: "hasAriaLabel" }] : /* istanbul ignore next */ []));
@@ -1795,18 +1659,9 @@ var bsIconAddon_component = /*#__PURE__*/Object.freeze({
1795
1659
  BsIconAddonComponent: BsIconAddonComponent
1796
1660
  });
1797
1661
 
1798
- /**
1799
- * Renderer for the `bs-button` addon kind.
1800
- *
1801
- * Renders a Bootstrap `btn-outline-{severity}` button. Click dispatch
1802
- * (preset / actionRef / action precedence, multi-set warning, `disabled` /
1803
- * `loading` resolution) lives on `NgForgeAddonAction`; this component
1804
- * focuses on the visual layer.
1805
- */
1806
1662
  class BsButtonAddonComponent {
1807
1663
  action = injectNgForgeAddonAction();
1808
- /** Re-exposed for template binding — same signal stored on the directive. */
1809
- addon = this.action.addon;
1664
+ addon = this.action.addon;
1810
1665
  label = computed(() => this.addon().label, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
1811
1666
  ariaLabel = computed(() => this.addon().ariaLabel, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
1812
1667
  iconClass = computed(() => {
@@ -1873,11 +1728,7 @@ var bsButtonAddon_component = /*#__PURE__*/Object.freeze({
1873
1728
  BsButtonAddonComponent: BsButtonAddonComponent
1874
1729
  });
1875
1730
 
1876
- // Field components
1877
1731
 
1878
- /**
1879
- * Generated bundle index. Do not edit.
1880
- */
1881
1732
 
1882
1733
  export { BOOTSTRAP_CONFIG, BOOTSTRAP_FIELD_TYPES, BS_INPUT_TYPE_OVERRIDE, BsButtonAddonComponent, BsButtonFieldComponent, BsCheckboxFieldComponent, BsDatepickerFieldComponent, BsField, BsIconAddonComponent, BsInputFieldComponent, BsMultiCheckboxFieldComponent, BsRadioFieldComponent, BsSelectFieldComponent, BsSliderFieldComponent, BsTextareaFieldComponent, BsToggleFieldComponent, withBootstrapAddons, withBootstrapFields };
1883
1734
  //# sourceMappingURL=ng-forge-dynamic-forms-bootstrap.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ng-forge-dynamic-forms-bootstrap.mjs","sources":["../../../../packages/dynamic-forms-bootstrap/src/lib/fields/button/bs-button.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/button/index.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/checkbox/bs-checkbox.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/directives/input-constraints.directive.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/datepicker/bs-datepicker.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/models/bootstrap-config.token.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/addons/preset-actions.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/tokens/input-type-override.token.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/input/bs-input.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/multi-checkbox/bs-multi-checkbox.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/radio/bs-radio-group.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/radio/bs-radio.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/select/bs-select.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/slider/bs-slider.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/textarea/bs-textarea.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/toggle/bs-toggle.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/index.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/types/types.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/button/bs-button.mapper.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/button/bs-specific-button.mapper.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/config/bootstrap-field-config.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/types/registry-augmentation.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/providers/bootstrap-providers.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/addons/bs-icon-addon.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/addons/bs-button-addon.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/index.ts","../../../../packages/dynamic-forms-bootstrap/src/ng-forge-dynamic-forms-bootstrap.ts"],"sourcesContent":["import { AsyncPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { DynamicTextPipe, FormEvent } from '@ng-forge/dynamic-forms';\nimport { injectNgForgeAction, NgForgeActionHost } from '@ng-forge/dynamic-forms/integration';\nimport { BsButtonProps } from './bs-button.type';\n\n@Component({\n selector: 'df-bs-button',\n imports: [DynamicTextPipe, AsyncPipe],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeActionHost],\n template: `\n @let buttonId = action.key() + '-button';\n <button\n [id]=\"buttonId\"\n [type]=\"buttonType()\"\n [disabled]=\"action.disabled()\"\n [class]=\"buttonClasses()\"\n [attr.tabindex]=\"action.tabIndex()\"\n [attr.data-testid]=\"buttonTestId()\"\n (click)=\"onClick()\"\n >\n {{ action.label() | dynamicText | async }}\n </button>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class BsButtonFieldComponent<TEvent extends FormEvent> {\n protected readonly action = injectNgForgeAction<TEvent>();\n\n readonly props = input<BsButtonProps>();\n\n /** Resolved button type — defaults to 'button' unless overridden via props. */\n readonly buttonType = computed(() => this.props()?.type ?? 'button');\n\n readonly buttonTestId = computed(() => `${this.buttonType()}-${this.action.key()}`);\n\n readonly buttonClasses = computed(() => {\n const p = this.props();\n const variant = p?.variant || 'primary';\n const outline = p?.outline ? 'outline-' : '';\n\n return [\n 'btn',\n `btn-${outline}${variant}`,\n p?.size === 'sm' && 'btn-sm',\n p?.size === 'lg' && 'btn-lg',\n p?.block && 'w-100',\n p?.active && 'active',\n this.action.className(),\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n /** Submit buttons let the native form handle submission; other buttons dispatch via the directive. */\n onClick(): void {\n if (this.buttonType() === 'submit') return;\n this.action.dispatch();\n }\n}\n","// Public API - types for type safety\nexport type {\n BsButtonProps,\n BsButtonField,\n BsSubmitButtonField,\n BsNextButtonField,\n BsPreviousButtonField,\n AddArrayItemButtonField,\n PrependArrayItemButtonField,\n InsertArrayItemButtonField,\n RemoveArrayItemButtonField,\n PopArrayItemButtonField,\n ShiftArrayItemButtonField,\n} from './bs-button.type';\n\n// Public API - component\nexport { default as BsButtonFieldComponent } from './bs-button.component';\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { BsCheckboxProps } from './bs-checkbox.type';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-bs-checkbox',\n imports: [FormField, DynamicTextPipe, AsyncPipe, NgForgeControl],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field(); @let checkboxId = ngf.key() + '-checkbox';\n\n <div\n class=\"form-check\"\n [class.form-switch]=\"props()?.switch\"\n [class.form-check-inline]=\"props()?.inline\"\n [class.form-check-reverse]=\"props()?.reverse\"\n [attr.hidden]=\"f().hidden() || null\"\n >\n <input\n ngForgeControl\n type=\"checkbox\"\n [formField]=\"f\"\n [id]=\"checkboxId\"\n [indeterminate]=\"props()?.indeterminate ?? false\"\n class=\"form-check-input\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n />\n <label [for]=\"checkboxId\" class=\"form-check-label\">\n {{ ngf.label() | dynamicText | async }}\n </label>\n </div>\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (props()?.hint; as hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\" [attr.hidden]=\"f().hidden() || null\">{{ hint | dynamicText | async }}</div>\n }\n `,\n styles: [\n `\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class BsCheckboxFieldComponent {\n protected readonly ngf = injectNgForgeField<boolean>();\n\n readonly props = input<BsCheckboxProps>();\n}\n","import { Directive, ElementRef, inject, input } from '@angular/core';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\n\n/**\n * Directive to set min, max, and step attributes on form inputs\n */\n@Directive({\n selector: '[dfBsInputConstraints]',\n})\nexport class InputConstraintsDirective {\n readonly dfMin = input<number | string | null | undefined>();\n readonly dfMax = input<number | string | null | undefined>();\n readonly dfStep = input<number | string | null | undefined>();\n\n private readonly el = inject<ElementRef<HTMLInputElement>>(ElementRef);\n\n private readonly minEffect = explicitEffect([this.dfMin], ([minValue]) => {\n const nativeElement = this.el.nativeElement;\n if (minValue !== null && minValue !== undefined) {\n nativeElement.setAttribute('min', String(minValue));\n } else {\n nativeElement.removeAttribute('min');\n }\n });\n\n private readonly maxEffect = explicitEffect([this.dfMax], ([maxValue]) => {\n const nativeElement = this.el.nativeElement;\n if (maxValue !== null && maxValue !== undefined) {\n nativeElement.setAttribute('max', String(maxValue));\n } else {\n nativeElement.removeAttribute('max');\n }\n });\n\n private readonly stepEffect = explicitEffect([this.dfStep], ([stepValue]) => {\n const nativeElement = this.el.nativeElement;\n if (stepValue !== null && stepValue !== undefined) {\n nativeElement.setAttribute('step', String(stepValue));\n } else {\n nativeElement.removeAttribute('step');\n }\n });\n}\n","import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { BsDatepickerProps } from './bs-datepicker.type';\nimport { AsyncPipe } from '@angular/common';\nimport { InputConstraintsDirective } from '../../directives/input-constraints.directive';\n\n@Component({\n selector: 'df-bs-datepicker',\n imports: [FormField, DynamicTextPipe, AsyncPipe, InputConstraintsDirective, NgForgeControl],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field(); @let p = props(); @let inputId = ngf.key() + '-input';\n @if (p?.floatingLabel) {\n <!-- Floating label variant -->\n <div class=\"form-floating mb-3\">\n <input\n ngForgeControl\n dfBsInputConstraints\n [formField]=\"f\"\n [id]=\"inputId\"\n type=\"date\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [dfMin]=\"minAsString()\"\n [dfMax]=\"maxAsString()\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-control\"\n [class.form-control-sm]=\"p?.size === 'sm'\"\n [class.form-control-lg]=\"p?.size === 'lg'\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n />\n @if (ngf.label()) {\n <label [for]=\"inputId\">{{ ngf.label() | dynamicText | async }}</label>\n }\n @if (p?.validFeedback && f().valid() && f().touched()) {\n <div class=\"valid-feedback d-block\">\n {{ p?.validFeedback | dynamicText | async }}\n </div>\n }\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n }\n </div>\n } @else {\n <!-- Standard variant -->\n <div class=\"mb-3\">\n @if (ngf.label()) {\n <label [for]=\"inputId\" class=\"form-label\">{{ ngf.label() | dynamicText | async }}</label>\n }\n\n <input\n ngForgeControl\n dfBsInputConstraints\n [formField]=\"f\"\n [id]=\"inputId\"\n type=\"date\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [dfMin]=\"minAsString()\"\n [dfMax]=\"maxAsString()\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-control\"\n [class.form-control-sm]=\"p?.size === 'sm'\"\n [class.form-control-lg]=\"p?.size === 'lg'\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n />\n\n @if (p?.validFeedback && f().valid() && f().touched()) {\n <div class=\"valid-feedback d-block\">\n {{ p?.validFeedback | dynamicText | async }}\n </div>\n }\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (p?.hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ p?.hint | dynamicText | async }}</div>\n }\n </div>\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n styles: [\n `\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n})\nexport default class BsDatepickerFieldComponent {\n protected readonly ngf = injectNgForgeField<string>();\n\n readonly minDate = input<Date | string | null>(null);\n readonly maxDate = input<Date | string | null>(null);\n readonly startAt = input<Date | null>(null);\n readonly props = input<BsDatepickerProps>();\n\n // Helper methods to convert Date to string for HTML attributes\n readonly minAsString = computed(() => {\n const min = this.minDate();\n return min instanceof Date ? min.toISOString().split('T')[0] : min;\n });\n\n readonly maxAsString = computed(() => {\n const max = this.maxDate();\n return max instanceof Date ? max.toISOString().split('T')[0] : max;\n });\n}\n","import { InjectionToken } from '@angular/core';\nimport { BootstrapConfig } from './bootstrap-config';\n\n/**\n * Injection token for Bootstrap form configuration.\n * Use this to provide global configuration for Bootstrap form fields.\n *\n * @example\n * ```typescript\n * import { provideDynamicForm } from '@ng-forge/dynamic-forms';\n * import { withBootstrapFields } from '@ng-forge/dynamic-forms-bootstrap';\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideDynamicForm(\n * ...withBootstrapFields({\n * floatingLabel: true,\n * size: 'lg'\n * })\n * )\n * ]\n * };\n * ```\n */\nexport const BOOTSTRAP_CONFIG = new InjectionToken<BootstrapConfig>('BOOTSTRAP_CONFIG');\n","import type { AddonActionContext, AddonActionPreset, PresetCollaborators } from '@ng-forge/dynamic-forms';\nimport { runPresetAction } from '@ng-forge/dynamic-forms';\n\nexport type { PresetCollaborators };\n\n/** Bootstrap adapter binding for the shared preset runner. */\nexport function runBsPresetAction(preset: AddonActionPreset, ctx: AddonActionContext, collaborators: PresetCollaborators): Promise<void> {\n return runPresetAction(preset, ctx, collaborators, 'Bootstrap', 'bs-input');\n}\n","import { InjectionToken, WritableSignal } from '@angular/core';\n\n/**\n * Per-field writable signal that overrides the input's `type` attribute.\n *\n * Provided at the `bs-input` field component level. The button addon's\n * `'toggle-password-visibility'` preset writes to it; the field component\n * reads it to compute its effective `type`.\n *\n * Optional from a button's perspective — when the button is hosted inside a\n * field that doesn't provide this token (e.g., textarea or a future\n * non-input field), the toggle preset is a no-op.\n */\nexport const BS_INPUT_TYPE_OVERRIDE = new InjectionToken<WritableSignal<string | undefined>>('BS_INPUT_TYPE_OVERRIDE');\n","import { AsyncPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, forwardRef, inject, input, signal } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport {\n AddonActionContext,\n AddonActionPreset,\n DfAddonSlot,\n DynamicFormLogger,\n DynamicTextPipe,\n FIELD_SIGNAL_CONTEXT,\n WrapperFieldInputs,\n} from '@ng-forge/dynamic-forms';\nimport {\n ADDON_PRESET_HANDLER,\n AddonPresetHandler,\n injectNgForgeAddons,\n injectNgForgeField,\n NgForgeAddons,\n NgForgeControl,\n NgForgeFieldHost,\n} from '@ng-forge/dynamic-forms/integration';\nimport { BOOTSTRAP_CONFIG } from '../../models/bootstrap-config.token';\nimport { runBsPresetAction } from '../../addons/preset-actions';\nimport { BS_INPUT_TYPE_OVERRIDE } from '../../tokens/input-type-override.token';\nimport { BsInputAddon, BsInputProps } from './bs-input.type';\n\n@Component({\n selector: 'df-bs-input',\n imports: [FormField, DynamicTextPipe, AsyncPipe, NgForgeControl, DfAddonSlot],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost, NgForgeAddons],\n template: `\n @let f = ngf.field(); @let p = props(); @let inputId = ngf.key() + '-input';\n @if (floatingLabel()) {\n <div class=\"mb-3\">\n @if (ngfa.hasAddons()) {\n <div class=\"input-group\">\n @for (a of ngfa.prefixAddons(); track $index) {\n <span class=\"input-group-text\">\n <df-addon-slot [addon]=\"a\" [fieldInputs]=\"fieldInputs()\" [hidden]=\"ngfa.hiddenSignalCache().get(a)\" />\n </span>\n }\n <div class=\"form-floating\">\n <input\n ngForgeControl\n [formField]=\"f\"\n [id]=\"inputId\"\n [type]=\"type()\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-control\"\n [class.form-control-sm]=\"size() === 'sm'\"\n [class.form-control-lg]=\"size() === 'lg'\"\n [class.form-control-plaintext]=\"p?.plaintext\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n />\n @if (ngf.label()) {\n <label [for]=\"inputId\">{{ ngf.label() | dynamicText | async }}</label>\n }\n </div>\n @for (a of ngfa.suffixAddons(); track $index) {\n <span class=\"input-group-text\">\n <df-addon-slot [addon]=\"a\" [fieldInputs]=\"fieldInputs()\" [hidden]=\"ngfa.hiddenSignalCache().get(a)\" />\n </span>\n }\n </div>\n } @else {\n <div class=\"form-floating\">\n <input\n ngForgeControl\n [formField]=\"f\"\n [id]=\"inputId\"\n [type]=\"type()\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-control\"\n [class.form-control-sm]=\"size() === 'sm'\"\n [class.form-control-lg]=\"size() === 'lg'\"\n [class.form-control-plaintext]=\"p?.plaintext\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n />\n @if (ngf.label()) {\n <label [for]=\"inputId\">{{ ngf.label() | dynamicText | async }}</label>\n }\n </div>\n }\n @if (p?.validFeedback && f().valid() && f().touched()) {\n <div class=\"valid-feedback d-block\">\n {{ p?.validFeedback | dynamicText | async }}\n </div>\n }\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n }\n </div>\n } @else {\n <div class=\"mb-3\">\n @if (ngf.label()) {\n <label [for]=\"inputId\" class=\"form-label\">{{ ngf.label() | dynamicText | async }}</label>\n }\n @if (ngfa.hasAddons()) {\n <div class=\"input-group\">\n @for (a of ngfa.prefixAddons(); track $index) {\n <span class=\"input-group-text\">\n <df-addon-slot [addon]=\"a\" [fieldInputs]=\"fieldInputs()\" [hidden]=\"ngfa.hiddenSignalCache().get(a)\" />\n </span>\n }\n <input\n ngForgeControl\n [formField]=\"f\"\n [id]=\"inputId\"\n [type]=\"type()\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-control\"\n [class.form-control-sm]=\"size() === 'sm'\"\n [class.form-control-lg]=\"size() === 'lg'\"\n [class.form-control-plaintext]=\"p?.plaintext\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n />\n @for (a of ngfa.suffixAddons(); track $index) {\n <span class=\"input-group-text\">\n <df-addon-slot [addon]=\"a\" [fieldInputs]=\"fieldInputs()\" [hidden]=\"ngfa.hiddenSignalCache().get(a)\" />\n </span>\n }\n </div>\n } @else {\n <input\n ngForgeControl\n [formField]=\"f\"\n [id]=\"inputId\"\n [type]=\"type()\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-control\"\n [class.form-control-sm]=\"size() === 'sm'\"\n [class.form-control-lg]=\"size() === 'lg'\"\n [class.form-control-plaintext]=\"p?.plaintext\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n />\n }\n @if (p?.validFeedback && f().valid() && f().touched()) {\n <div class=\"valid-feedback d-block\">\n {{ p?.validFeedback | dynamicText | async }}\n </div>\n }\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (p?.hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ p?.hint | dynamicText | async }}</div>\n }\n </div>\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: BS_INPUT_TYPE_OVERRIDE,\n useFactory: () => signal<string | undefined>(undefined),\n },\n {\n // Adapter-specific preset semantics for `bs-button` addons (clear /\n // reset / paste / copy / toggle-password-visibility). The directive\n // (`NgForgeAddonAction`) delegates here when an addon configures a\n // `preset`. Per-bs-input-instance so the `typeOverride` signal is\n // scoped to one field.\n provide: ADDON_PRESET_HANDLER,\n useFactory: (): AddonPresetHandler => {\n const typeOverride = inject(BS_INPUT_TYPE_OVERRIDE);\n const fsc = inject(FIELD_SIGNAL_CONTEXT, { optional: true });\n const logger = inject(DynamicFormLogger);\n // forwardRef for baselineType only — host.props()?.type gates toggle-password-visibility.\n const host = inject(forwardRef(() => BsInputFieldComponent));\n return {\n run: (preset: string, ctx: AddonActionContext) => {\n const fieldKey = ctx.field.key;\n return runBsPresetAction(preset as AddonActionPreset, ctx, {\n typeOverride,\n fieldValueSetter: ctx.setValue,\n fieldDefaultValueGetter:\n fsc && fieldKey ? () => (fsc.defaultValues() as Record<string, unknown> | undefined)?.[fieldKey] : undefined,\n baselineType: () => host.props()?.type,\n logger,\n });\n },\n };\n },\n },\n ],\n styles: [\n `\n :host([hidden]) {\n display: none !important;\n }\n /* Per-side padding on the .input-group-text addon containers — each\n side is its own knob so consumers can tune the prefix's gap from\n the border (outer-left), the prefix's gap to the input text\n (inner-right), and the symmetric suffix counterparts independently. */\n :host {\n --df-bs-addon-prefix-outer-padding: 0.75rem;\n --df-bs-addon-prefix-inner-padding: 0.75rem;\n --df-bs-addon-suffix-inner-padding: 0.75rem;\n --df-bs-addon-suffix-outer-padding: 0.75rem;\n }\n :host ::ng-deep .input-group > .input-group-text:first-child {\n padding-left: var(--df-bs-addon-prefix-outer-padding);\n padding-right: var(--df-bs-addon-prefix-inner-padding);\n }\n :host ::ng-deep .input-group > .input-group-text:last-child {\n padding-left: var(--df-bs-addon-suffix-inner-padding);\n padding-right: var(--df-bs-addon-suffix-outer-padding);\n }\n /* bs-button addons live inside .input-group-text for visual parity with\n bs-icon (shared grey container). Strip the inner .btn's own visual\n chrome (border, background, focus ring) so the button blends with\n the addon container — done via Bootstrap's own CSS variables so the\n cascade reaches the rendered <button> in any theme. No !important. */\n :host ::ng-deep .input-group-text df-bs-button-addon .btn {\n --bs-btn-bg: transparent;\n --bs-btn-color: var(--bs-body-color);\n --bs-btn-border-color: transparent;\n --bs-btn-hover-bg: rgba(127, 127, 127, 0.12);\n --bs-btn-hover-color: var(--bs-body-color);\n --bs-btn-hover-border-color: transparent;\n --bs-btn-active-bg: rgba(127, 127, 127, 0.18);\n --bs-btn-active-border-color: transparent;\n --bs-btn-focus-shadow-rgb: 0, 0, 0;\n --bs-btn-padding-x: 0;\n --bs-btn-padding-y: 0;\n box-shadow: none;\n }\n :host ::ng-deep .input-group-text df-bs-button-addon .btn:focus-visible {\n /* 2px solid for WCAG 2.4.11; currentColor adapts to light/dark themes. */\n box-shadow: none;\n outline: 2px solid currentColor;\n outline-offset: 2px;\n }\n `,\n ],\n})\nexport default class BsInputFieldComponent {\n private bootstrapConfig = inject(BOOTSTRAP_CONFIG, { optional: true });\n\n protected readonly ngf = injectNgForgeField<string>();\n protected readonly ngfa = injectNgForgeAddons<BsInputAddon>();\n\n readonly props = input<BsInputProps>();\n\n /**\n * Wrapper-style host bag pushed by `DfFieldOutlet`. Declared at the\n * component level so `setInputIfDeclared` (which uses\n * `reflectComponentType`) can write it.\n */\n readonly fieldInputs = input<WrapperFieldInputs | undefined>();\n\n /** Per-instance type override populated by `toggle-password-visibility` preset. */\n private readonly typeOverride = inject(BS_INPUT_TYPE_OVERRIDE);\n\n readonly size = computed(() => this.props()?.size ?? this.bootstrapConfig?.size);\n readonly floatingLabel = computed(() => this.props()?.floatingLabel ?? this.bootstrapConfig?.floatingLabel ?? false);\n\n /** Override (set by `toggle-password-visibility` preset) wins over `props().type`. */\n protected readonly type = computed(() => this.typeOverride() ?? this.props()?.type ?? 'text');\n}\n","import { ChangeDetectionStrategy, Component, computed, input, linkedSignal } from '@angular/core';\nimport { DynamicTextPipe, FieldOption, ValueType } from '@ng-forge/dynamic-forms';\nimport { injectNgForgeField, NgForgeFieldHost, isEqual, NgForgeControl } from '@ng-forge/dynamic-forms/integration';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { BsMultiCheckboxProps } from './bs-multi-checkbox.type';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-bs-multi-checkbox',\n imports: [DynamicTextPipe, AsyncPipe, NgForgeControl],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field();\n @let checked = checkedValuesMap();\n @if (ngf.label(); as label) {\n <div class=\"form-label\">{{ label | dynamicText | async }}</div>\n }\n\n <div class=\"checkbox-group\">\n @for (option of options(); track option.value; let i = $index) {\n <div\n class=\"form-check\"\n [class.form-switch]=\"props()?.switch\"\n [class.form-check-inline]=\"props()?.inline\"\n [class.form-check-reverse]=\"props()?.reverse\"\n >\n <input\n ngForgeControl\n type=\"checkbox\"\n [id]=\"ngf.key() + '_' + i\"\n [checked]=\"checked['' + option.value]\"\n [disabled]=\"f().disabled() || option.disabled\"\n (change)=\"onCheckboxChange(option, $event)\"\n class=\"form-check-input\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n />\n <label [for]=\"ngf.key() + '_' + i\" class=\"form-check-label\">\n {{ option.label | dynamicText | async }}\n </label>\n </div>\n }\n </div>\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (props()?.hint; as hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ hint | dynamicText | async }}</div>\n }\n `,\n styles: [\n `\n :host {\n display: block;\n }\n\n .checkbox-group {\n margin-bottom: 0.5rem;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class BsMultiCheckboxFieldComponent {\n protected readonly ngf = injectNgForgeField<ValueType[]>();\n\n readonly options = input<FieldOption<ValueType>[]>([]);\n readonly props = input<BsMultiCheckboxProps>();\n\n /** Computed map of checked option values for O(1) lookup in template */\n readonly checkedValuesMap = computed(() => {\n const map: Record<string, boolean> = {};\n for (const opt of this.valueViewModel()) {\n map[String(opt.value)] = true;\n }\n return map;\n });\n\n valueViewModel = linkedSignal<FieldOption<ValueType>[]>(\n () => {\n const currentValues = this.ngf.field()().value();\n return this.options().filter((option) => currentValues.includes(option.value));\n },\n { equal: isEqual },\n );\n\n constructor() {\n explicitEffect([this.valueViewModel], ([selectedOptions]: [FieldOption<ValueType>[]]) => {\n const selectedValues = selectedOptions.map((option: FieldOption<ValueType>) => option.value);\n\n if (!isEqual(selectedValues, this.ngf.field()().value())) {\n this.ngf.field()().value.set(selectedValues);\n }\n });\n\n explicitEffect([this.options], ([options]: [FieldOption<ValueType>[]]) => {\n const values = options.map((option: FieldOption<ValueType>) => option.value);\n const uniqueValues = new Set(values);\n\n if (values.length !== uniqueValues.size) {\n const duplicates = values.filter((value, index) => values.indexOf(value) !== index);\n throw new Error(`Duplicate option values detected in bs-multi-checkbox: ${duplicates.join(', ')}`);\n }\n });\n }\n\n onCheckboxChange(option: FieldOption<ValueType>, event: Event): void {\n const checked = (event.target as HTMLInputElement).checked;\n this.valueViewModel.update((currentOptions: FieldOption<ValueType>[]) => {\n if (checked) {\n return currentOptions.some((opt: FieldOption<ValueType>) => opt.value === option.value)\n ? currentOptions\n : [...currentOptions, option];\n } else {\n return currentOptions.filter((opt: FieldOption<ValueType>) => opt.value !== option.value);\n }\n });\n }\n}\n","import { ChangeDetectionStrategy, Component, input, model } from '@angular/core';\nimport type { FormValueControl } from '@angular/forms/signals';\nimport { DynamicText, DynamicTextPipe, FieldOption, ValueType } from '@ng-forge/dynamic-forms';\nimport { NgForgeControl } from '@ng-forge/dynamic-forms/integration';\nimport { AsyncPipe } from '@angular/common';\n\nexport interface BsRadioGroupProps {\n /**\n * Display radio buttons inline (horizontal)\n */\n inline?: boolean;\n /**\n * Reverse the position of the radio button and label\n */\n reverse?: boolean;\n /**\n * Display as button group instead of radio buttons\n */\n buttonGroup?: boolean;\n /**\n * Button size when using button group\n */\n buttonSize?: 'sm' | 'lg';\n /**\n * Hint text to display below the radio group\n */\n hint?: DynamicText;\n}\n\n/**\n * Bootstrap radio group implementing FormValueControl. Rendered inside\n * `df-bs-radio` — each `<input type=\"radio\">` carries `ngForgeControl`, so\n * the marker absorbs meta + aria from the ambient parent NgForgeField.\n */\n@Component({\n selector: 'df-bs-radio-group',\n imports: [DynamicTextPipe, AsyncPipe, NgForgeControl],\n template: `\n @let props = properties();\n @if (props?.buttonGroup) {\n <div class=\"btn-group\" role=\"group\" [attr.aria-label]=\"label() | dynamicText | async\">\n @for (option of options(); track option.value; let i = $index) {\n <input\n ngForgeControl\n type=\"radio\"\n [name]=\"name()\"\n [value]=\"option.value\"\n [checked]=\"value() === option.value\"\n (change)=\"onRadioChange(option.value)\"\n [disabled]=\"disabled() || option.disabled || false\"\n class=\"btn-check\"\n [id]=\"name() + '_' + i\"\n autocomplete=\"off\"\n />\n <label\n class=\"btn btn-outline-primary\"\n [class.btn-sm]=\"props?.buttonSize === 'sm'\"\n [class.btn-lg]=\"props?.buttonSize === 'lg'\"\n [for]=\"name() + '_' + i\"\n >\n {{ option.label | dynamicText | async }}\n </label>\n }\n </div>\n } @else {\n @for (option of options(); track option.value; let i = $index) {\n <div class=\"form-check\" [class.form-check-inline]=\"props?.inline\" [class.form-check-reverse]=\"props?.reverse\">\n <input\n ngForgeControl\n type=\"radio\"\n [name]=\"name()\"\n [value]=\"option.value\"\n [checked]=\"value() === option.value\"\n (change)=\"onRadioChange(option.value)\"\n [disabled]=\"disabled() || option.disabled || false\"\n class=\"form-check-input\"\n [id]=\"name() + '_' + i\"\n />\n <label class=\"form-check-label\" [for]=\"name() + '_' + i\">\n {{ option.label | dynamicText | async }}\n </label>\n </div>\n }\n }\n `,\n styles: [\n `\n :host {\n display: block;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BsRadioGroupComponent implements FormValueControl<ValueType | undefined> {\n // Value model - FormField directive binds form value to this\n readonly value = model<ValueType | undefined>(undefined);\n\n // Optional FormValueControl properties - Field directive will bind these\n readonly disabled = input<boolean>(false);\n readonly readonly = input<boolean>(false);\n readonly name = input<string>('');\n\n // Component-specific inputs\n readonly label = input<DynamicText>();\n readonly options = input.required<FieldOption<ValueType>[]>();\n readonly properties = input<BsRadioGroupProps>();\n\n /**\n * Handle radio button change event\n */\n protected onRadioChange(newValue: ValueType): void {\n if (!this.disabled() && !this.readonly()) {\n this.value.set(newValue);\n }\n }\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { DynamicTextPipe, FieldOption, ValueType } from '@ng-forge/dynamic-forms';\nimport { injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { BsRadioProps } from './bs-radio.type';\nimport { AsyncPipe } from '@angular/common';\nimport { BsRadioGroupComponent } from './bs-radio-group.component';\n\n@Component({\n selector: 'df-bs-radio',\n imports: [BsRadioGroupComponent, FormField, DynamicTextPipe, AsyncPipe],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field();\n\n <div class=\"mb-3\">\n @if (ngf.label(); as label) {\n <div class=\"form-label\">{{ label | dynamicText | async }}</div>\n }\n\n <df-bs-radio-group [formField]=\"f\" [label]=\"ngf.label()\" [options]=\"options()\" [properties]=\"props()\" />\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (props()?.hint; as hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ hint | dynamicText | async }}</div>\n }\n </div>\n `,\n styles: [\n `\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class BsRadioFieldComponent {\n protected readonly ngf = injectNgForgeField<ValueType>();\n\n readonly options = input<FieldOption<ValueType>[]>([]);\n readonly props = input<BsRadioProps>();\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { DynamicTextPipe, FieldOption } from '@ng-forge/dynamic-forms';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { BsSelectProps } from './bs-select.type';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-bs-select',\n imports: [FormField, DynamicTextPipe, AsyncPipe, NgForgeControl],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field(); @let selectId = ngf.key() + '-select';\n\n <div class=\"mb-3\">\n @if (ngf.label(); as label) {\n <label [for]=\"selectId\" class=\"form-label\">{{ label | dynamicText | async }}</label>\n }\n <select\n ngForgeControl\n [formField]=\"f\"\n [id]=\"selectId\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-select\"\n [class.form-select-sm]=\"props()?.size === 'sm'\"\n [class.form-select-lg]=\"props()?.size === 'lg'\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [multiple]=\"props()?.multiple || false\"\n [size]=\"props()?.htmlSize\"\n >\n @if (ngf.placeholder(); as placeholder) {\n <option value=\"\" disabled [selected]=\"!f().value()\">{{ placeholder | dynamicText | async }}</option>\n }\n @for (option of options(); track option.value) {\n <option [value]=\"option.value\" [disabled]=\"option.disabled || false\" [selected]=\"isSelected(option.value, f().value())\">\n {{ option.label | dynamicText | async }}\n </option>\n }\n </select>\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (props()?.hint; as hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ hint | dynamicText | async }}</div>\n }\n </div>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n styles: [\n `\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n})\nexport default class BsSelectFieldComponent {\n protected readonly ngf = injectNgForgeField<string>();\n\n readonly options = input<FieldOption<string>[]>([]);\n readonly props = input<BsSelectProps>();\n\n defaultCompare = Object.is;\n\n protected isSelected(optionValue: string, fieldValue: string | string[] | null): boolean {\n const compareWith = this.props()?.compareWith || this.defaultCompare;\n\n if (Array.isArray(fieldValue)) {\n return fieldValue.some((v) => compareWith(v, optionValue));\n }\n\n return fieldValue !== null && compareWith(fieldValue, optionValue);\n }\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { BsSliderProps } from './bs-slider.type';\nimport { AsyncPipe } from '@angular/common';\nimport { InputConstraintsDirective } from '../../directives/input-constraints.directive';\n\n@Component({\n selector: 'df-bs-slider',\n imports: [FormField, DynamicTextPipe, AsyncPipe, InputConstraintsDirective, NgForgeControl],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field(); @let inputId = ngf.key() + '-input';\n\n <div class=\"mb-3\">\n @if (ngf.label(); as label) {\n <label [for]=\"inputId\" class=\"form-label\">\n {{ label | dynamicText | async }}\n @if (props()?.showValue) {\n <span class=\"ms-2 badge bg-secondary\"> {{ props()?.valuePrefix }}{{ f().value() }}{{ props()?.valueSuffix }} </span>\n }\n </label>\n }\n\n <input\n ngForgeControl\n type=\"range\"\n dfBsInputConstraints\n [formField]=\"f\"\n [id]=\"inputId\"\n [dfMin]=\"f().min?.() ?? props()?.min ?? min()\"\n [dfMax]=\"f().max?.() ?? props()?.max ?? max()\"\n [dfStep]=\"step() ?? props()?.step ?? 1\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-range\"\n />\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (props()?.hint; as hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ hint | dynamicText | async }}</div>\n }\n </div>\n `,\n styles: [\n `\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class BsSliderFieldComponent {\n protected readonly ngf = injectNgForgeField<number>();\n\n readonly min = input<number>(0);\n readonly max = input<number>(100);\n readonly step = input<number>();\n\n readonly props = input<BsSliderProps>();\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { BsTextareaProps } from './bs-textarea.type';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-bs-textarea',\n imports: [FormField, DynamicTextPipe, AsyncPipe, NgForgeControl],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field(); @let p = props(); @let textareaId = ngf.key() + '-textarea';\n @if (p?.floatingLabel) {\n <!-- Floating label variant -->\n <div class=\"form-floating mb-3\">\n <textarea\n ngForgeControl\n [formField]=\"f\"\n [id]=\"textareaId\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-control\"\n [class.form-control-sm]=\"p?.size === 'sm'\"\n [class.form-control-lg]=\"p?.size === 'lg'\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n ></textarea>\n\n @if (ngf.label()) {\n <label [for]=\"textareaId\">{{ ngf.label() | dynamicText | async }}</label>\n }\n @if (p?.validFeedback && f().valid() && f().touched()) {\n <div class=\"valid-feedback d-block\">\n {{ p?.validFeedback | dynamicText | async }}\n </div>\n }\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (p?.hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ p?.hint | dynamicText | async }}</div>\n }\n </div>\n } @else {\n <!-- Standard variant -->\n <div class=\"mb-3\">\n @if (ngf.label()) {\n <label [for]=\"textareaId\" class=\"form-label\">{{ ngf.label() | dynamicText | async }}</label>\n }\n\n <textarea\n ngForgeControl\n [formField]=\"f\"\n [id]=\"textareaId\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-control\"\n [class.form-control-sm]=\"p?.size === 'sm'\"\n [class.form-control-lg]=\"p?.size === 'lg'\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n ></textarea>\n\n @if (p?.validFeedback && f().valid() && f().touched()) {\n <div class=\"valid-feedback d-block\">\n {{ p?.validFeedback | dynamicText | async }}\n </div>\n }\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (p?.hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ p?.hint | dynamicText | async }}</div>\n }\n </div>\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n styles: [\n `\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n})\nexport default class BsTextareaFieldComponent {\n protected readonly ngf = injectNgForgeField<string>();\n\n readonly props = input<BsTextareaProps>();\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { BsToggleProps } from './bs-toggle.type';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-bs-toggle',\n imports: [FormField, DynamicTextPipe, AsyncPipe, NgForgeControl],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field(); @let inputId = ngf.key() + '-input';\n\n <div\n class=\"form-check form-switch\"\n [class.form-check-inline]=\"props()?.inline\"\n [class.form-check-reverse]=\"props()?.reverse\"\n [class.form-switch-sm]=\"props()?.size === 'sm'\"\n [class.form-switch-lg]=\"props()?.size === 'lg'\"\n [attr.hidden]=\"f().hidden() || null\"\n >\n <input\n ngForgeControl\n type=\"checkbox\"\n [formField]=\"f\"\n [id]=\"inputId\"\n class=\"form-check-input\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n />\n <label [for]=\"inputId\" class=\"form-check-label\">\n {{ ngf.label() | dynamicText | async }}\n </label>\n </div>\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (props()?.hint; as hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\" [attr.hidden]=\"f().hidden() || null\">{{ hint | dynamicText | async }}</div>\n }\n `,\n styles: [\n `\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n /* Custom size variants for switches */\n .form-switch-sm .form-check-input {\n width: 1.75rem;\n height: 1rem;\n font-size: 0.875rem;\n }\n\n .form-switch-lg .form-check-input {\n width: 3rem;\n height: 1.75rem;\n font-size: 1.125rem;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class BsToggleFieldComponent {\n protected readonly ngf = injectNgForgeField<boolean>();\n\n readonly props = input<BsToggleProps>();\n}\n","// Public exports for bootstrap field components and types\n\nexport { BsButtonFieldComponent } from './button';\nexport type {\n BsButtonProps,\n BsButtonField,\n BsSubmitButtonField,\n BsNextButtonField,\n BsPreviousButtonField,\n AddArrayItemButtonField,\n PrependArrayItemButtonField,\n InsertArrayItemButtonField,\n RemoveArrayItemButtonField,\n PopArrayItemButtonField,\n ShiftArrayItemButtonField,\n} from './button';\n\nexport { BsCheckboxFieldComponent } from './checkbox';\nexport type { BsCheckboxProps, BsCheckboxField, BsCheckboxComponent } from './checkbox';\n\nexport { BsDatepickerFieldComponent } from './datepicker';\nexport type { BsDatepickerProps, BsDatepickerField, BsDatepickerComponent } from './datepicker';\n\nexport { BsInputFieldComponent } from './input';\nexport type { BsInputProps, BsInputField, BsInputComponent } from './input';\n\nexport { BsMultiCheckboxFieldComponent } from './multi-checkbox';\nexport type { BsMultiCheckboxProps, BsMultiCheckboxField, BsMultiCheckboxComponent } from './multi-checkbox';\n\nexport { BsRadioFieldComponent } from './radio';\nexport type { BsRadioProps, BsRadioField, BsRadioComponent } from './radio';\n\nexport { BsSelectFieldComponent } from './select';\nexport type { BsSelectProps, BsSelectField, BsSelectComponent } from './select';\n\nexport { BsSliderFieldComponent } from './slider';\nexport type { BsSliderProps, BsSliderField, BsSliderComponent } from './slider';\n\nexport { BsTextareaFieldComponent } from './textarea';\nexport type { BsTextareaProps, BsTextareaField, BsTextareaComponent } from './textarea';\n\nexport { BsToggleFieldComponent } from './toggle';\nexport type { BsToggleProps, BsToggleField, BsToggleComponent } from './toggle';\n","/**\n * Bootstrap field type constants\n * Based on available field components in the /fields folder\n */\nexport const BsField = {\n Input: 'input',\n Select: 'select',\n Checkbox: 'checkbox',\n Button: 'button',\n Submit: 'submit',\n Next: 'next',\n Previous: 'previous',\n AddArrayItem: 'addArrayItem',\n PrependArrayItem: 'prependArrayItem',\n InsertArrayItem: 'insertArrayItem',\n RemoveArrayItem: 'removeArrayItem',\n PopArrayItem: 'popArrayItem',\n ShiftArrayItem: 'shiftArrayItem',\n Textarea: 'textarea',\n Radio: 'radio',\n MultiCheckbox: 'multi-checkbox',\n Datepicker: 'datepicker',\n Slider: 'slider',\n Toggle: 'toggle',\n} as const;\n\nexport type BsFieldType = (typeof BsField)[keyof typeof BsField];\n","import { computed, inject, isSignal, Signal } from '@angular/core';\nimport { ARRAY_CONTEXT, buildBaseInputs, DEFAULT_PROPS, FieldDef } from '@ng-forge/dynamic-forms';\n\n/**\n * Generic button mapper for custom events or basic buttons.\n * For specific button types (submit, next, prev, add/remove array items),\n * use the dedicated field types and their specific mappers.\n *\n * Supports template property for array events (AppendArrayItemEvent, PrependArrayItemEvent, InsertArrayItemEvent)\n * which enables the $template token in eventArgs.\n *\n * @param fieldDef The button field definition\n * @returns Signal containing Record of input names to values for ngComponentOutlet\n */\nexport function buttonFieldMapper(fieldDef: FieldDef<Record<string, unknown>>): Signal<Record<string, unknown>> {\n const defaultProps = inject(DEFAULT_PROPS);\n const arrayContext = inject(ARRAY_CONTEXT, { optional: true });\n\n return computed(() => {\n const baseInputs = buildBaseInputs(fieldDef, defaultProps());\n\n const inputs: Record<string, unknown> = {\n ...baseInputs,\n };\n\n if (fieldDef.disabled !== undefined) {\n inputs['disabled'] = fieldDef.disabled;\n }\n\n if (fieldDef.hidden !== undefined) {\n inputs['hidden'] = fieldDef.hidden;\n }\n\n // Add event binding for button events\n if ('event' in fieldDef && fieldDef.event !== undefined) {\n inputs['event'] = fieldDef.event;\n }\n\n // Add eventArgs binding if provided\n if ('eventArgs' in fieldDef && fieldDef.eventArgs !== undefined) {\n inputs['eventArgs'] = fieldDef.eventArgs;\n }\n\n // Add eventContext for token resolution (supports $template, $arrayKey, $index, etc.)\n const template = 'template' in fieldDef ? fieldDef.template : undefined;\n if (template || arrayContext) {\n // Read signal value if index is a signal (supports differential updates)\n const getIndex = () => {\n if (!arrayContext) return -1;\n return isSignal(arrayContext.index) ? arrayContext.index() : arrayContext.index;\n };\n\n inputs['eventContext'] = {\n key: fieldDef.key,\n index: getIndex(),\n arrayKey: arrayContext?.arrayKey ?? '',\n formValue: arrayContext?.formValue ?? {},\n template,\n };\n }\n\n return inputs;\n });\n}\n","/**\n * Navigation button mappers for Bootstrap - re-exported from integration package.\n *\n * These mappers handle submit, next, and previous buttons with proper\n * disabled state resolution based on form validity and options.\n */\nexport { submitButtonFieldMapper, nextButtonFieldMapper, previousButtonFieldMapper } from '@ng-forge/dynamic-forms/integration';\n","import { FieldTypeDefinition } from '@ng-forge/dynamic-forms';\nimport {\n addArrayItemButtonMapper,\n checkboxFieldMapper,\n datepickerFieldMapper,\n insertArrayItemButtonMapper,\n optionsFieldMapper,\n popArrayItemButtonMapper,\n prependArrayItemButtonMapper,\n removeArrayItemButtonMapper,\n shiftArrayItemButtonMapper,\n valueFieldMapper,\n} from '@ng-forge/dynamic-forms/integration';\nimport { BsField } from '../types/types';\nimport { buttonFieldMapper } from '../fields/button/bs-button.mapper';\nimport { nextButtonFieldMapper, previousButtonFieldMapper, submitButtonFieldMapper } from '../fields/button/bs-specific-button.mapper';\n\nconst VALUE_FIELD_TYPES_BASE = {\n renderReadyWhen: ['field'],\n} as const;\n\nconst BUTTON_FIELD_TYPES_BASE = {\n renderReadyWhen: [],\n valueHandling: 'exclude',\n} as const;\n\nexport const BOOTSTRAP_FIELD_TYPES: FieldTypeDefinition[] = [\n {\n name: BsField.Input,\n loadComponent: () => import('../fields/input/bs-input.component'),\n mapper: valueFieldMapper,\n propsToMeta: ['type'],\n scope: ['text-input', 'numeric'],\n addons: {\n slots: ['prefix', 'suffix'],\n },\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Select,\n loadComponent: () => import('../fields/select/bs-select.component'),\n mapper: optionsFieldMapper,\n scope: 'single-select',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Checkbox,\n loadComponent: () => import('../fields/checkbox/bs-checkbox.component'),\n mapper: checkboxFieldMapper,\n scope: 'boolean',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Button,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: buttonFieldMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Submit,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: submitButtonFieldMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Next,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: nextButtonFieldMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Previous,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: previousButtonFieldMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.AddArrayItem,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: addArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.PrependArrayItem,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: prependArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.InsertArrayItem,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: insertArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.RemoveArrayItem,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: removeArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.PopArrayItem,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: popArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.ShiftArrayItem,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: shiftArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Textarea,\n loadComponent: () => import('../fields/textarea/bs-textarea.component'),\n mapper: valueFieldMapper,\n propsToMeta: ['rows'],\n scope: 'text-input',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Radio,\n loadComponent: () => import('../fields/radio/bs-radio.component'),\n mapper: optionsFieldMapper,\n scope: 'single-select',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: BsField.MultiCheckbox,\n loadComponent: () => import('../fields/multi-checkbox/bs-multi-checkbox.component'),\n mapper: optionsFieldMapper,\n scope: 'multi-select',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Datepicker,\n loadComponent: () => import('../fields/datepicker/bs-datepicker.component'),\n mapper: datepickerFieldMapper,\n scope: 'date',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Slider,\n loadComponent: () => import('../fields/slider/bs-slider.component'),\n mapper: valueFieldMapper,\n scope: 'numeric',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Toggle,\n loadComponent: () => import('../fields/toggle/bs-toggle.component'),\n mapper: checkboxFieldMapper,\n scope: 'boolean',\n ...VALUE_FIELD_TYPES_BASE,\n },\n];\n","/**\n * Module augmentation for @ng-forge/dynamic-form\n * This file augments the FieldRegistryLeaves interface to include\n * all Bootstrap field types provided by this library.\n */\n\nimport type { FormEvent } from '@ng-forge/dynamic-forms';\nimport type {\n AddArrayItemButtonField,\n BsButtonField,\n BsCheckboxField,\n BsDatepickerField,\n BsInputField,\n BsMultiCheckboxField,\n BsNextButtonField,\n BsPreviousButtonField,\n BsRadioField,\n BsSelectField,\n BsSliderField,\n BsSubmitButtonField,\n BsTextareaField,\n BsToggleField,\n InsertArrayItemButtonField,\n PopArrayItemButtonField,\n PrependArrayItemButtonField,\n RemoveArrayItemButtonField,\n ShiftArrayItemButtonField,\n} from '../fields';\n\ndeclare module '@ng-forge/dynamic-forms' {\n interface FieldRegistryLeaves {\n input: BsInputField;\n select: BsSelectField<unknown>;\n checkbox: BsCheckboxField;\n button: BsButtonField<FormEvent>;\n submit: BsSubmitButtonField;\n next: BsNextButtonField;\n previous: BsPreviousButtonField;\n addArrayItem: AddArrayItemButtonField;\n prependArrayItem: PrependArrayItemButtonField;\n insertArrayItem: InsertArrayItemButtonField;\n removeArrayItem: RemoveArrayItemButtonField;\n popArrayItem: PopArrayItemButtonField;\n shiftArrayItem: ShiftArrayItemButtonField;\n textarea: BsTextareaField;\n radio: BsRadioField<unknown>;\n 'multi-checkbox': BsMultiCheckboxField<unknown>;\n datepicker: BsDatepickerField;\n slider: BsSliderField;\n toggle: BsToggleField;\n }\n}\n","import type { Provider } from '@angular/core';\nimport { ADDON_KIND_DEFINITIONS, DynamicFormError, type AddonKindDefinition, type FieldTypeDefinition } from '@ng-forge/dynamic-forms';\nimport { BOOTSTRAP_FIELD_TYPES } from '../config/bootstrap-field-config';\nimport { BootstrapConfig } from '../models/bootstrap-config';\nimport { BOOTSTRAP_CONFIG } from '../models/bootstrap-config.token';\nimport type { BsButtonAddon, BsIconAddon } from '../types/addons';\n\n/**\n * Field type definitions for Bootstrap components.\n */\nexport type BootstrapFieldTypes = FieldTypeDefinition[];\n\ntype BootstrapConfigFeature = {\n ɵkind: 'bootstrap-config';\n ɵproviders: Provider[];\n};\n\n/**\n * Default `withBootstrapFields()` shape — field defs + the auto-included\n * addons feature so `bs-icon` / `bs-button` work out of the box.\n */\ntype BootstrapFieldsWithAddons = [...BootstrapFieldTypes, BootstrapAddonsFeature];\n\ntype BootstrapFieldsWithConfig = [...BootstrapFieldTypes, BootstrapAddonsFeature, BootstrapConfigFeature];\n\n/**\n * Provides Bootstrap field type definitions for the dynamic form system,\n * with Bootstrap-shipped addon kinds (`bs-icon`, `bs-button`) auto-included\n * so addons work out of the box.\n *\n * If you want addons WITHOUT the field types (rare — e.g., adding addons to\n * a form that uses custom fields), call `withBootstrapAddons()` standalone.\n *\n * @param config - Optional global configuration for Bootstrap form fields\n *\n * @example\n * ```typescript\n * // Application-level setup — addons (bs-icon, bs-button) ship in automatically\n * import { ApplicationConfig } from '@angular/core';\n * import { provideDynamicForm } from '@ng-forge/dynamic-forms';\n * import { withBootstrapFields } from '@ng-forge/dynamic-forms-bootstrap';\n *\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideDynamicForm(...withBootstrapFields())\n * ]\n * };\n * ```\n *\n * @example\n * ```typescript\n * // With global configuration\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideDynamicForm(\n * ...withBootstrapFields({\n * floatingLabel: true,\n * size: 'lg'\n * })\n * )\n * ]\n * };\n * ```\n *\n * @returns Tuple of field type definitions, the addons feature, and\n * optionally a config feature.\n */\nexport function withBootstrapFields(): BootstrapFieldsWithAddons;\nexport function withBootstrapFields(config: BootstrapConfig): BootstrapFieldsWithConfig;\nexport function withBootstrapFields(config: BootstrapConfig | undefined): BootstrapFieldsWithAddons | BootstrapFieldsWithConfig;\nexport function withBootstrapFields(config?: BootstrapConfig): BootstrapFieldsWithAddons | BootstrapFieldsWithConfig {\n // Always include the addons feature — bs-icon / bs-button are part of\n // the canonical Bootstrap surface.\n const base: unknown[] = [...BOOTSTRAP_FIELD_TYPES, withBootstrapAddons()];\n\n if (config) {\n base.push({\n ɵkind: 'bootstrap-config',\n ɵproviders: [{ provide: BOOTSTRAP_CONFIG, useValue: config }],\n } satisfies BootstrapConfigFeature);\n return base as BootstrapFieldsWithConfig;\n }\n\n return base as BootstrapFieldsWithAddons;\n}\n\n/* -- Bootstrap addon kinds --------------------------------------------- */\n\nconst BS_ICON_KIND: AddonKindDefinition<BsIconAddon> = {\n kind: 'bs-icon',\n loadComponent: () => import('../addons/bs-icon-addon.component').then((m) => m.BsIconAddonComponent),\n validate: (addon, fieldKey) => {\n if (typeof addon.icon !== 'string' || addon.icon.length === 0) {\n throw new DynamicFormError(`Addon kind 'bs-icon' requires a non-empty 'icon' string (field: '${fieldKey}').`);\n }\n },\n};\n\nconst BS_BUTTON_KIND: AddonKindDefinition<BsButtonAddon> = {\n kind: 'bs-button',\n loadComponent: () => import('../addons/bs-button-addon.component').then((m) => m.BsButtonAddonComponent),\n validate: (addon, fieldKey) => {\n // Exactly one of preset / actionRef / action — validator drops the addon\n // (with warning) if the rule is violated.\n const set = [addon.preset, addon.actionRef, addon.action].filter((v) => v !== undefined);\n if (set.length > 1) {\n throw new DynamicFormError(\n `Addon kind 'bs-button' on field '${fieldKey}' has more than one of preset/actionRef/action — exactly one allowed.`,\n );\n }\n // Icon-only buttons require ariaLabel for screen readers.\n if (addon.icon && !addon.label && !addon.ariaLabel) {\n throw new DynamicFormError(`Addon kind 'bs-button' on field '${fieldKey}' is icon-only — provide 'ariaLabel' for accessibility.`);\n }\n },\n};\n\n/**\n * Feature kind discriminant for the Bootstrap addons feature. Matches core's\n * `'addons'` kind so providers flow through the standard addon-kind pipeline\n * in `provideDynamicForm`.\n */\ntype BootstrapAddonsFeature = {\n ɵkind: 'addons';\n ɵproviders: Provider[];\n};\n\n/**\n * Register Bootstrap-shipped addon kinds (`bs-icon`, `bs-button`) standalone.\n *\n * **Most users don't need this** — `withBootstrapFields()` auto-includes\n * these kinds. Call `withBootstrapAddons()` directly only when you want\n * Bootstrap addon kinds without the Bootstrap field types (e.g., a custom\n * field set that wants to render `bs-icon` prefixes), or when you're\n * stitching addons through a different DI scope.\n *\n * @example\n * ```typescript\n * // Custom field types + Bootstrap addon kinds.\n * provideDynamicForm(\n * ...myCustomFields(),\n * withBootstrapAddons(),\n * );\n * ```\n *\n * Adapter authors who need to override a kind with a customised renderer\n * should call `withCustomAddon(...)` directly instead.\n */\nexport function withBootstrapAddons(): BootstrapAddonsFeature {\n return {\n ɵkind: 'addons',\n ɵproviders: [\n { provide: ADDON_KIND_DEFINITIONS, useValue: BS_ICON_KIND, multi: true },\n { provide: ADDON_KIND_DEFINITIONS, useValue: BS_BUTTON_KIND, multi: true },\n ],\n };\n}\n","import { AsyncPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { DynamicTextPipe, WrapperFieldInputs } from '@ng-forge/dynamic-forms';\nimport type { BsIconAddon } from '../types/addons';\n\n/**\n * Renderer for the `bs-icon` addon kind.\n *\n * Outputs `<i class=\"bi bi-{icon}\">`. The host is set `aria-hidden=\"true\"`\n * by default; if the addon supplies an `ariaLabel`, it is applied so the\n * icon is announced by screen readers.\n */\n@Component({\n selector: 'df-bs-icon-addon',\n imports: [AsyncPipe, DynamicTextPipe],\n template: `<i [class]=\"iconClass()\" [attr.aria-label]=\"(ariaLabel() | dynamicText | async) ?? null\"></i>`,\n host: {\n '[attr.aria-hidden]': 'hasAriaLabel() ? null : \"true\"',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BsIconAddonComponent {\n readonly addon = input.required<BsIconAddon>();\n /** Accepted for contract uniformity — `NgComponentOutlet` setInput is strict; every kind must declare it. */\n readonly fieldInputs = input<WrapperFieldInputs | undefined>();\n\n protected readonly iconClass = computed(() => `bi bi-${this.addon().icon}`);\n protected readonly ariaLabel = computed(() => this.addon().ariaLabel);\n protected readonly hasAriaLabel = computed(() => this.addon().ariaLabel !== undefined);\n}\n","import { AsyncPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed } from '@angular/core';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms';\nimport { injectNgForgeAddonAction, NgForgeAddonAction } from '@ng-forge/dynamic-forms/integration';\nimport type { BsButtonAddon } from '../types/addons';\n\n/**\n * Renderer for the `bs-button` addon kind.\n *\n * Renders a Bootstrap `btn-outline-{severity}` button. Click dispatch\n * (preset / actionRef / action precedence, multi-set warning, `disabled` /\n * `loading` resolution) lives on `NgForgeAddonAction`; this component\n * focuses on the visual layer.\n */\n@Component({\n selector: 'df-bs-button-addon',\n imports: [DynamicTextPipe, AsyncPipe],\n hostDirectives: [NgForgeAddonAction],\n template: `\n <button\n type=\"button\"\n [class]=\"buttonClass()\"\n [disabled]=\"action.disabled() || action.loading()\"\n [attr.aria-label]=\"(ariaLabel() | dynamicText | async) ?? null\"\n [attr.aria-busy]=\"action.loading() || null\"\n (click)=\"action.dispatch()\"\n >\n @if (action.loading()) {\n <!-- Visually-hidden role=status text gives a reliable AT announcement (VO/JAWS/NVDA). -->\n <span class=\"spinner-border spinner-border-sm\" aria-hidden=\"true\"></span>\n <span class=\"visually-hidden\" role=\"status\">Loading…</span>\n } @else if (iconClass(); as ic) {\n <i [class]=\"ic\" aria-hidden=\"true\"></i>\n }\n @if (label(); as l) {\n <span>{{ l | dynamicText | async }}</span>\n }\n </button>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BsButtonAddonComponent {\n protected readonly action = injectNgForgeAddonAction<BsButtonAddon>();\n\n /** Re-exposed for template binding — same signal stored on the directive. */\n protected readonly addon = this.action.addon;\n\n protected readonly label = computed(() => this.addon().label);\n protected readonly ariaLabel = computed(() => this.addon().ariaLabel);\n protected readonly iconClass = computed(() => {\n const icon = this.addon().icon;\n return icon ? `bi bi-${icon}` : '';\n });\n protected readonly buttonClass = computed(() => `btn btn-outline-${this.addon().severity ?? 'secondary'}`);\n}\n","// Field components\nexport {\n BsButtonFieldComponent,\n BsCheckboxFieldComponent,\n BsDatepickerFieldComponent,\n BsInputFieldComponent,\n BsMultiCheckboxFieldComponent,\n BsRadioFieldComponent,\n BsSelectFieldComponent,\n BsSliderFieldComponent,\n BsTextareaFieldComponent,\n BsToggleFieldComponent,\n} from './fields';\nexport type {\n BsButtonProps,\n BsButtonField,\n BsSubmitButtonField,\n BsNextButtonField,\n BsPreviousButtonField,\n AddArrayItemButtonField,\n PrependArrayItemButtonField,\n InsertArrayItemButtonField,\n RemoveArrayItemButtonField,\n PopArrayItemButtonField,\n ShiftArrayItemButtonField,\n BsCheckboxProps,\n BsCheckboxField,\n BsCheckboxComponent,\n BsDatepickerProps,\n BsDatepickerField,\n BsDatepickerComponent,\n BsInputProps,\n BsInputField,\n BsInputComponent,\n BsMultiCheckboxProps,\n BsMultiCheckboxField,\n BsMultiCheckboxComponent,\n BsRadioProps,\n BsRadioField,\n BsRadioComponent,\n BsSelectProps,\n BsSelectField,\n BsSelectComponent,\n BsSliderProps,\n BsSliderField,\n BsSliderComponent,\n BsTextareaProps,\n BsTextareaField,\n BsTextareaComponent,\n BsToggleProps,\n BsToggleField,\n BsToggleComponent,\n} from './fields';\n\n// Configuration\nexport { BOOTSTRAP_FIELD_TYPES } from './config/bootstrap-field-config';\nexport type { BootstrapConfig } from './models';\nexport { BOOTSTRAP_CONFIG } from './models';\n\n// Types and constants\nexport { BsField, type BsFieldType } from './types/types';\nexport type { BsFormProps, BsFormConfig } from './types/form-config';\n\n// IMPORTANT: side-effect imports — these augment global type registries\n// (FieldRegistryLeaves, DynamicFormAddonRegistry) so `type: 'input'`,\n// `kind: 'bs-icon'`, and similar resolve at the call site. Without these,\n// consumer typechecks fall back to the empty base registries.\nimport './types/registry-augmentation';\nimport './types/addons';\n\n// Providers\nexport { withBootstrapFields, withBootstrapAddons } from './providers/bootstrap-providers';\n\n// Addon kinds\nexport { BsIconAddonComponent } from './addons/bs-icon-addon.component';\nexport { BsButtonAddonComponent } from './addons/bs-button-addon.component';\nexport type { BsIconAddon, BsButtonAddon, BsAddon } from './types/addons';\nexport type { BsInputAddon, BsAddonExtensions } from './fields/input/bs-input.type';\nexport { BS_INPUT_TYPE_OVERRIDE } from './tokens/input-type-override.token';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ng-forge-dynamic-forms-bootstrap.mjs","mappings":"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;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACD;AACD;;AAEE;AACA;;AAEA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;AACD;;AAEE;AACA;AACA;AACA;AACD;;;;ACvHG;;;;AAOA;;AAEgC;AAClC;;AAGF;AACF;AAEA;AAEA;AACE;AACA;AACA;AACE;AACE;;;;AAKN;AACE;AACA;AACA;;AAIE;AACE;;QAKF;AACE;;;;;;AAkBF;AACA;;;AAGC;;AAEL;;;ACrFW;;AAIU;AACA;AACA;;AAPR;;;;AATF;AACT;AACA;AACA;AACA;AACE;AACD;;AAEF;;;;;;;;;;ICwBoB;AAEA;AACA;AACA;;;AAGnB;AACmB;;AAZR;;;;;;;;;;;;;;;;;;;;;;;;AA3BF;AACT;AACA;;AAEA;;;;;;;;;;;;;;;;;;;;AAoBC;;AAEF","names":[],"ignoreList":[],"sources":["../../../../packages/dynamic-forms-bootstrap/src/lib/fields/button/bs-button.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/checkbox/bs-checkbox.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/directives/input-constraints.directive.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/datepicker/bs-datepicker.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/addons/preset-actions.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/input/bs-input.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/multi-checkbox/bs-multi-checkbox.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/radio/bs-radio-group.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/radio/bs-radio.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/select/bs-select.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/slider/bs-slider.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/textarea/bs-textarea.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/toggle/bs-toggle.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/types/types.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/fields/button/bs-button.mapper.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/config/bootstrap-field-config.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/providers/bootstrap-providers.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/addons/bs-icon-addon.component.ts","../../../../packages/dynamic-forms-bootstrap/src/lib/addons/bs-button-addon.component.ts"],"sourcesContent":["import { AsyncPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { DynamicTextPipe, FormEvent } from '@ng-forge/dynamic-forms';\nimport { injectNgForgeAction, NgForgeActionHost } from '@ng-forge/dynamic-forms/integration';\nimport { BsButtonProps } from './bs-button.type';\n\n@Component({\n selector: 'df-bs-button',\n imports: [DynamicTextPipe, AsyncPipe],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeActionHost],\n template: `\n @let buttonId = action.key() + '-button';\n <button\n [id]=\"buttonId\"\n [type]=\"buttonType()\"\n [disabled]=\"action.disabled()\"\n [class]=\"buttonClasses()\"\n [attr.tabindex]=\"action.tabIndex()\"\n [attr.data-testid]=\"buttonTestId()\"\n (click)=\"onClick()\"\n >\n {{ action.label() | dynamicText | async }}\n </button>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class BsButtonFieldComponent<TEvent extends FormEvent> {\n protected readonly action = injectNgForgeAction<TEvent>();\n\n readonly props = input<BsButtonProps>();\n\n /** Resolved button type — defaults to 'button' unless overridden via props. */\n readonly buttonType = computed(() => this.props()?.type ?? 'button');\n\n readonly buttonTestId = computed(() => `${this.buttonType()}-${this.action.key()}`);\n\n readonly buttonClasses = computed(() => {\n const p = this.props();\n const variant = p?.variant || 'primary';\n const outline = p?.outline ? 'outline-' : '';\n\n return [\n 'btn',\n `btn-${outline}${variant}`,\n p?.size === 'sm' && 'btn-sm',\n p?.size === 'lg' && 'btn-lg',\n p?.block && 'w-100',\n p?.active && 'active',\n this.action.className(),\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n /** Submit buttons let the native form handle submission; other buttons dispatch via the directive. */\n onClick(): void {\n if (this.buttonType() === 'submit') return;\n this.action.dispatch();\n }\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { BsCheckboxProps } from './bs-checkbox.type';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-bs-checkbox',\n imports: [FormField, DynamicTextPipe, AsyncPipe, NgForgeControl],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field(); @let checkboxId = ngf.key() + '-checkbox';\n\n <div\n class=\"form-check\"\n [class.form-switch]=\"props()?.switch\"\n [class.form-check-inline]=\"props()?.inline\"\n [class.form-check-reverse]=\"props()?.reverse\"\n [attr.hidden]=\"f().hidden() || null\"\n >\n <input\n ngForgeControl\n type=\"checkbox\"\n [formField]=\"f\"\n [id]=\"checkboxId\"\n [indeterminate]=\"props()?.indeterminate ?? false\"\n class=\"form-check-input\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n />\n <label [for]=\"checkboxId\" class=\"form-check-label\">\n {{ ngf.label() | dynamicText | async }}\n </label>\n </div>\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (props()?.hint; as hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\" [attr.hidden]=\"f().hidden() || null\">{{ hint | dynamicText | async }}</div>\n }\n `,\n styles: [\n `\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class BsCheckboxFieldComponent {\n protected readonly ngf = injectNgForgeField<boolean>();\n\n readonly props = input<BsCheckboxProps>();\n}\n","import { Directive, ElementRef, inject, input } from '@angular/core';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\n\n/** Directive to set min, max, and step attributes on form inputs */\n@Directive({\n selector: '[dfBsInputConstraints]',\n})\nexport class InputConstraintsDirective {\n readonly dfMin = input<number | string | null | undefined>();\n readonly dfMax = input<number | string | null | undefined>();\n readonly dfStep = input<number | string | null | undefined>();\n\n private readonly el = inject<ElementRef<HTMLInputElement>>(ElementRef);\n\n private readonly minEffect = explicitEffect([this.dfMin], ([minValue]) => {\n const nativeElement = this.el.nativeElement;\n if (minValue !== null && minValue !== undefined) {\n nativeElement.setAttribute('min', String(minValue));\n } else {\n nativeElement.removeAttribute('min');\n }\n });\n\n private readonly maxEffect = explicitEffect([this.dfMax], ([maxValue]) => {\n const nativeElement = this.el.nativeElement;\n if (maxValue !== null && maxValue !== undefined) {\n nativeElement.setAttribute('max', String(maxValue));\n } else {\n nativeElement.removeAttribute('max');\n }\n });\n\n private readonly stepEffect = explicitEffect([this.dfStep], ([stepValue]) => {\n const nativeElement = this.el.nativeElement;\n if (stepValue !== null && stepValue !== undefined) {\n nativeElement.setAttribute('step', String(stepValue));\n } else {\n nativeElement.removeAttribute('step');\n }\n });\n}\n","import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { BsDatepickerProps } from './bs-datepicker.type';\nimport { AsyncPipe } from '@angular/common';\nimport { InputConstraintsDirective } from '../../directives/input-constraints.directive';\n\n@Component({\n selector: 'df-bs-datepicker',\n imports: [FormField, DynamicTextPipe, AsyncPipe, InputConstraintsDirective, NgForgeControl],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field(); @let p = props(); @let inputId = ngf.key() + '-input';\n @if (p?.floatingLabel) {\n <!-- Floating label variant -->\n <div class=\"form-floating mb-3\">\n <input\n ngForgeControl\n dfBsInputConstraints\n [formField]=\"f\"\n [id]=\"inputId\"\n type=\"date\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [dfMin]=\"minAsString()\"\n [dfMax]=\"maxAsString()\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-control\"\n [class.form-control-sm]=\"p?.size === 'sm'\"\n [class.form-control-lg]=\"p?.size === 'lg'\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n />\n @if (ngf.label()) {\n <label [for]=\"inputId\">{{ ngf.label() | dynamicText | async }}</label>\n }\n @if (p?.validFeedback && f().valid() && f().touched()) {\n <div class=\"valid-feedback d-block\">\n {{ p?.validFeedback | dynamicText | async }}\n </div>\n }\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n }\n </div>\n } @else {\n <!-- Standard variant -->\n <div class=\"mb-3\">\n @if (ngf.label()) {\n <label [for]=\"inputId\" class=\"form-label\">{{ ngf.label() | dynamicText | async }}</label>\n }\n\n <input\n ngForgeControl\n dfBsInputConstraints\n [formField]=\"f\"\n [id]=\"inputId\"\n type=\"date\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [dfMin]=\"minAsString()\"\n [dfMax]=\"maxAsString()\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-control\"\n [class.form-control-sm]=\"p?.size === 'sm'\"\n [class.form-control-lg]=\"p?.size === 'lg'\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n />\n\n @if (p?.validFeedback && f().valid() && f().touched()) {\n <div class=\"valid-feedback d-block\">\n {{ p?.validFeedback | dynamicText | async }}\n </div>\n }\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (p?.hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ p?.hint | dynamicText | async }}</div>\n }\n </div>\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n styles: [\n `\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n})\nexport default class BsDatepickerFieldComponent {\n protected readonly ngf = injectNgForgeField<string>();\n\n readonly minDate = input<Date | string | null>(null);\n readonly maxDate = input<Date | string | null>(null);\n readonly startAt = input<Date | null>(null);\n readonly props = input<BsDatepickerProps>();\n\n // Helper methods to convert Date to string for HTML attributes\n readonly minAsString = computed(() => {\n const min = this.minDate();\n return min instanceof Date ? min.toISOString().split('T')[0] : min;\n });\n\n readonly maxAsString = computed(() => {\n const max = this.maxDate();\n return max instanceof Date ? max.toISOString().split('T')[0] : max;\n });\n}\n","import type { AddonActionContext, AddonActionPreset, PresetCollaborators } from '@ng-forge/dynamic-forms';\nimport { runPresetAction } from '@ng-forge/dynamic-forms';\n\nexport type { PresetCollaborators };\n\n/** Bootstrap adapter binding for the shared preset runner. */\nexport function runBsPresetAction(preset: AddonActionPreset, ctx: AddonActionContext, collaborators: PresetCollaborators): Promise<void> {\n return runPresetAction(preset, ctx, collaborators, 'Bootstrap', 'bs-input');\n}\n","import { AsyncPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, forwardRef, inject, input, signal } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport {\n AddonActionContext,\n AddonActionPreset,\n DfAddonSlot,\n DynamicFormLogger,\n DynamicTextPipe,\n FIELD_SIGNAL_CONTEXT,\n WrapperFieldInputs,\n} from '@ng-forge/dynamic-forms';\nimport {\n ADDON_PRESET_HANDLER,\n AddonPresetHandler,\n injectNgForgeAddons,\n injectNgForgeField,\n NgForgeAddons,\n NgForgeControl,\n NgForgeFieldHost,\n} from '@ng-forge/dynamic-forms/integration';\nimport { BOOTSTRAP_CONFIG } from '../../models/bootstrap-config.token';\nimport { runBsPresetAction } from '../../addons/preset-actions';\nimport { BS_INPUT_TYPE_OVERRIDE } from '../../tokens/input-type-override.token';\nimport { BsInputAddon, BsInputProps } from './bs-input.type';\n\n@Component({\n selector: 'df-bs-input',\n imports: [FormField, DynamicTextPipe, AsyncPipe, NgForgeControl, DfAddonSlot],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost, NgForgeAddons],\n template: `\n @let f = ngf.field(); @let p = props(); @let inputId = ngf.key() + '-input';\n @if (floatingLabel()) {\n <div class=\"mb-3\">\n @if (ngfa.hasAddons()) {\n <div class=\"input-group\">\n @for (a of ngfa.prefixAddons(); track $index) {\n <span class=\"input-group-text\">\n <df-addon-slot [addon]=\"a\" [fieldInputs]=\"fieldInputs()\" [hidden]=\"ngfa.hiddenSignalCache().get(a)\" />\n </span>\n }\n <div class=\"form-floating\">\n <input\n ngForgeControl\n [formField]=\"f\"\n [id]=\"inputId\"\n [type]=\"type()\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-control\"\n [class.form-control-sm]=\"size() === 'sm'\"\n [class.form-control-lg]=\"size() === 'lg'\"\n [class.form-control-plaintext]=\"p?.plaintext\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n />\n @if (ngf.label()) {\n <label [for]=\"inputId\">{{ ngf.label() | dynamicText | async }}</label>\n }\n </div>\n @for (a of ngfa.suffixAddons(); track $index) {\n <span class=\"input-group-text\">\n <df-addon-slot [addon]=\"a\" [fieldInputs]=\"fieldInputs()\" [hidden]=\"ngfa.hiddenSignalCache().get(a)\" />\n </span>\n }\n </div>\n } @else {\n <div class=\"form-floating\">\n <input\n ngForgeControl\n [formField]=\"f\"\n [id]=\"inputId\"\n [type]=\"type()\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-control\"\n [class.form-control-sm]=\"size() === 'sm'\"\n [class.form-control-lg]=\"size() === 'lg'\"\n [class.form-control-plaintext]=\"p?.plaintext\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n />\n @if (ngf.label()) {\n <label [for]=\"inputId\">{{ ngf.label() | dynamicText | async }}</label>\n }\n </div>\n }\n @if (p?.validFeedback && f().valid() && f().touched()) {\n <div class=\"valid-feedback d-block\">\n {{ p?.validFeedback | dynamicText | async }}\n </div>\n }\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n }\n </div>\n } @else {\n <div class=\"mb-3\">\n @if (ngf.label()) {\n <label [for]=\"inputId\" class=\"form-label\">{{ ngf.label() | dynamicText | async }}</label>\n }\n @if (ngfa.hasAddons()) {\n <div class=\"input-group\">\n @for (a of ngfa.prefixAddons(); track $index) {\n <span class=\"input-group-text\">\n <df-addon-slot [addon]=\"a\" [fieldInputs]=\"fieldInputs()\" [hidden]=\"ngfa.hiddenSignalCache().get(a)\" />\n </span>\n }\n <input\n ngForgeControl\n [formField]=\"f\"\n [id]=\"inputId\"\n [type]=\"type()\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-control\"\n [class.form-control-sm]=\"size() === 'sm'\"\n [class.form-control-lg]=\"size() === 'lg'\"\n [class.form-control-plaintext]=\"p?.plaintext\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n />\n @for (a of ngfa.suffixAddons(); track $index) {\n <span class=\"input-group-text\">\n <df-addon-slot [addon]=\"a\" [fieldInputs]=\"fieldInputs()\" [hidden]=\"ngfa.hiddenSignalCache().get(a)\" />\n </span>\n }\n </div>\n } @else {\n <input\n ngForgeControl\n [formField]=\"f\"\n [id]=\"inputId\"\n [type]=\"type()\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-control\"\n [class.form-control-sm]=\"size() === 'sm'\"\n [class.form-control-lg]=\"size() === 'lg'\"\n [class.form-control-plaintext]=\"p?.plaintext\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n />\n }\n @if (p?.validFeedback && f().valid() && f().touched()) {\n <div class=\"valid-feedback d-block\">\n {{ p?.validFeedback | dynamicText | async }}\n </div>\n }\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (p?.hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ p?.hint | dynamicText | async }}</div>\n }\n </div>\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: BS_INPUT_TYPE_OVERRIDE,\n useFactory: () => signal<string | undefined>(undefined),\n },\n {\n // Adapter-specific preset semantics for `bs-button` addons (clear /\n // reset / paste / copy / toggle-password-visibility). The directive\n // (`NgForgeAddonAction`) delegates here when an addon configures a\n // `preset`. Per-bs-input-instance so the `typeOverride` signal is\n // scoped to one field.\n provide: ADDON_PRESET_HANDLER,\n useFactory: (): AddonPresetHandler => {\n const typeOverride = inject(BS_INPUT_TYPE_OVERRIDE);\n const fsc = inject(FIELD_SIGNAL_CONTEXT, { optional: true });\n const logger = inject(DynamicFormLogger);\n // forwardRef for baselineType only — host.props()?.type gates toggle-password-visibility.\n const host = inject(forwardRef(() => BsInputFieldComponent));\n return {\n run: (preset: string, ctx: AddonActionContext) => {\n const fieldKey = ctx.field.key;\n return runBsPresetAction(preset as AddonActionPreset, ctx, {\n typeOverride,\n fieldValueSetter: ctx.setValue,\n fieldDefaultValueGetter:\n fsc && fieldKey ? () => (fsc.defaultValues() as Record<string, unknown> | undefined)?.[fieldKey] : undefined,\n baselineType: () => host.props()?.type,\n logger,\n });\n },\n };\n },\n },\n ],\n styles: [\n `\n :host([hidden]) {\n display: none !important;\n }\n /* Per-side padding on the .input-group-text addon containers — each\n side is its own knob so consumers can tune the prefix's gap from\n the border (outer-left), the prefix's gap to the input text\n (inner-right), and the symmetric suffix counterparts independently. */\n :host {\n --df-bs-addon-prefix-outer-padding: 0.75rem;\n --df-bs-addon-prefix-inner-padding: 0.75rem;\n --df-bs-addon-suffix-inner-padding: 0.75rem;\n --df-bs-addon-suffix-outer-padding: 0.75rem;\n }\n :host ::ng-deep .input-group > .input-group-text:first-child {\n padding-left: var(--df-bs-addon-prefix-outer-padding);\n padding-right: var(--df-bs-addon-prefix-inner-padding);\n }\n :host ::ng-deep .input-group > .input-group-text:last-child {\n padding-left: var(--df-bs-addon-suffix-inner-padding);\n padding-right: var(--df-bs-addon-suffix-outer-padding);\n }\n /* bs-button addons live inside .input-group-text for visual parity with\n bs-icon (shared grey container). Strip the inner .btn's own visual\n chrome (border, background, focus ring) so the button blends with\n the addon container — done via Bootstrap's own CSS variables so the\n cascade reaches the rendered <button> in any theme. No !important. */\n :host ::ng-deep .input-group-text df-bs-button-addon .btn {\n --bs-btn-bg: transparent;\n --bs-btn-color: var(--bs-body-color);\n --bs-btn-border-color: transparent;\n --bs-btn-hover-bg: rgba(127, 127, 127, 0.12);\n --bs-btn-hover-color: var(--bs-body-color);\n --bs-btn-hover-border-color: transparent;\n --bs-btn-active-bg: rgba(127, 127, 127, 0.18);\n --bs-btn-active-border-color: transparent;\n --bs-btn-focus-shadow-rgb: 0, 0, 0;\n --bs-btn-padding-x: 0;\n --bs-btn-padding-y: 0;\n box-shadow: none;\n }\n :host ::ng-deep .input-group-text df-bs-button-addon .btn:focus-visible {\n /* 2px solid for WCAG 2.4.11; currentColor adapts to light/dark themes. */\n box-shadow: none;\n outline: 2px solid currentColor;\n outline-offset: 2px;\n }\n `,\n ],\n})\nexport default class BsInputFieldComponent {\n private bootstrapConfig = inject(BOOTSTRAP_CONFIG, { optional: true });\n\n protected readonly ngf = injectNgForgeField<string>();\n protected readonly ngfa = injectNgForgeAddons<BsInputAddon>();\n\n readonly props = input<BsInputProps>();\n\n /**\n * Wrapper-style host bag pushed by `DfFieldOutlet`. Declared at the\n * component level so `setInputIfDeclared` (which uses\n * `reflectComponentType`) can write it.\n */\n readonly fieldInputs = input<WrapperFieldInputs | undefined>();\n\n /** Per-instance type override populated by `toggle-password-visibility` preset. */\n private readonly typeOverride = inject(BS_INPUT_TYPE_OVERRIDE);\n\n readonly size = computed(() => this.props()?.size ?? this.bootstrapConfig?.size);\n readonly floatingLabel = computed(() => this.props()?.floatingLabel ?? this.bootstrapConfig?.floatingLabel ?? false);\n\n /** Override (set by `toggle-password-visibility` preset) wins over `props().type`. */\n protected readonly type = computed(() => this.typeOverride() ?? this.props()?.type ?? 'text');\n}\n","import { ChangeDetectionStrategy, Component, computed, input, linkedSignal } from '@angular/core';\nimport { DynamicTextPipe, FieldOption, ValueType } from '@ng-forge/dynamic-forms';\nimport { injectNgForgeField, NgForgeFieldHost, isEqual, NgForgeControl } from '@ng-forge/dynamic-forms/integration';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { BsMultiCheckboxProps } from './bs-multi-checkbox.type';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-bs-multi-checkbox',\n imports: [DynamicTextPipe, AsyncPipe, NgForgeControl],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field();\n @let checked = checkedValuesMap();\n @if (ngf.label(); as label) {\n <div class=\"form-label\">{{ label | dynamicText | async }}</div>\n }\n\n <div class=\"checkbox-group\">\n @for (option of options(); track option.value; let i = $index) {\n <div\n class=\"form-check\"\n [class.form-switch]=\"props()?.switch\"\n [class.form-check-inline]=\"props()?.inline\"\n [class.form-check-reverse]=\"props()?.reverse\"\n >\n <input\n ngForgeControl\n type=\"checkbox\"\n [id]=\"ngf.key() + '_' + i\"\n [checked]=\"checked['' + option.value]\"\n [disabled]=\"f().disabled() || option.disabled\"\n (change)=\"onCheckboxChange(option, $event)\"\n class=\"form-check-input\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n />\n <label [for]=\"ngf.key() + '_' + i\" class=\"form-check-label\">\n {{ option.label | dynamicText | async }}\n </label>\n </div>\n }\n </div>\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (props()?.hint; as hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ hint | dynamicText | async }}</div>\n }\n `,\n styles: [\n `\n :host {\n display: block;\n }\n\n .checkbox-group {\n margin-bottom: 0.5rem;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class BsMultiCheckboxFieldComponent {\n protected readonly ngf = injectNgForgeField<ValueType[]>();\n\n readonly options = input<FieldOption<ValueType>[]>([]);\n readonly props = input<BsMultiCheckboxProps>();\n\n /** Computed map of checked option values for O(1) lookup in template */\n readonly checkedValuesMap = computed(() => {\n const map: Record<string, boolean> = {};\n for (const opt of this.valueViewModel()) {\n map[String(opt.value)] = true;\n }\n return map;\n });\n\n valueViewModel = linkedSignal<FieldOption<ValueType>[]>(\n () => {\n const currentValues = this.ngf.field()().value();\n return this.options().filter((option) => currentValues.includes(option.value));\n },\n { equal: isEqual },\n );\n\n constructor() {\n explicitEffect([this.valueViewModel], ([selectedOptions]: [FieldOption<ValueType>[]]) => {\n const selectedValues = selectedOptions.map((option: FieldOption<ValueType>) => option.value);\n\n if (!isEqual(selectedValues, this.ngf.field()().value())) {\n this.ngf.field()().value.set(selectedValues);\n }\n });\n\n explicitEffect([this.options], ([options]: [FieldOption<ValueType>[]]) => {\n const values = options.map((option: FieldOption<ValueType>) => option.value);\n const uniqueValues = new Set(values);\n\n if (values.length !== uniqueValues.size) {\n const duplicates = values.filter((value, index) => values.indexOf(value) !== index);\n throw new Error(`Duplicate option values detected in bs-multi-checkbox: ${duplicates.join(', ')}`);\n }\n });\n }\n\n onCheckboxChange(option: FieldOption<ValueType>, event: Event): void {\n const checked = (event.target as HTMLInputElement).checked;\n this.valueViewModel.update((currentOptions: FieldOption<ValueType>[]) => {\n if (checked) {\n return currentOptions.some((opt: FieldOption<ValueType>) => opt.value === option.value)\n ? currentOptions\n : [...currentOptions, option];\n } else {\n return currentOptions.filter((opt: FieldOption<ValueType>) => opt.value !== option.value);\n }\n });\n }\n}\n","import { ChangeDetectionStrategy, Component, input, model } from '@angular/core';\nimport type { FormValueControl } from '@angular/forms/signals';\nimport { DynamicText, DynamicTextPipe, FieldOption, ValueType } from '@ng-forge/dynamic-forms';\nimport { NgForgeControl } from '@ng-forge/dynamic-forms/integration';\nimport { AsyncPipe } from '@angular/common';\n\nexport interface BsRadioGroupProps {\n /** Display radio buttons inline (horizontal) */\n inline?: boolean;\n /** Reverse the position of the radio button and label */\n reverse?: boolean;\n /** Display as button group instead of radio buttons */\n buttonGroup?: boolean;\n /** Button size when using button group */\n buttonSize?: 'sm' | 'lg';\n /** Hint text to display below the radio group */\n hint?: DynamicText;\n}\n\n/**\n * Bootstrap radio group implementing FormValueControl. Rendered inside\n * `df-bs-radio` — each `<input type=\"radio\">` carries `ngForgeControl`, so\n * the marker absorbs meta + aria from the ambient parent NgForgeField.\n */\n@Component({\n selector: 'df-bs-radio-group',\n imports: [DynamicTextPipe, AsyncPipe, NgForgeControl],\n template: `\n @let props = properties();\n @if (props?.buttonGroup) {\n <div class=\"btn-group\" role=\"group\" [attr.aria-label]=\"label() | dynamicText | async\">\n @for (option of options(); track option.value; let i = $index) {\n <input\n ngForgeControl\n type=\"radio\"\n [name]=\"name()\"\n [value]=\"option.value\"\n [checked]=\"value() === option.value\"\n (change)=\"onRadioChange(option.value)\"\n [disabled]=\"disabled() || option.disabled || false\"\n class=\"btn-check\"\n [id]=\"name() + '_' + i\"\n autocomplete=\"off\"\n />\n <label\n class=\"btn btn-outline-primary\"\n [class.btn-sm]=\"props?.buttonSize === 'sm'\"\n [class.btn-lg]=\"props?.buttonSize === 'lg'\"\n [for]=\"name() + '_' + i\"\n >\n {{ option.label | dynamicText | async }}\n </label>\n }\n </div>\n } @else {\n @for (option of options(); track option.value; let i = $index) {\n <div class=\"form-check\" [class.form-check-inline]=\"props?.inline\" [class.form-check-reverse]=\"props?.reverse\">\n <input\n ngForgeControl\n type=\"radio\"\n [name]=\"name()\"\n [value]=\"option.value\"\n [checked]=\"value() === option.value\"\n (change)=\"onRadioChange(option.value)\"\n [disabled]=\"disabled() || option.disabled || false\"\n class=\"form-check-input\"\n [id]=\"name() + '_' + i\"\n />\n <label class=\"form-check-label\" [for]=\"name() + '_' + i\">\n {{ option.label | dynamicText | async }}\n </label>\n </div>\n }\n }\n `,\n styles: [\n `\n :host {\n display: block;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BsRadioGroupComponent implements FormValueControl<ValueType | undefined> {\n // Value model - FormField directive binds form value to this\n readonly value = model<ValueType | undefined>(undefined);\n\n // Optional FormValueControl properties - Field directive will bind these\n readonly disabled = input<boolean>(false);\n readonly readonly = input<boolean>(false);\n readonly name = input<string>('');\n\n // Component-specific inputs\n readonly label = input<DynamicText>();\n readonly options = input.required<FieldOption<ValueType>[]>();\n readonly properties = input<BsRadioGroupProps>();\n\n /** Handle radio button change event */\n protected onRadioChange(newValue: ValueType): void {\n if (!this.disabled() && !this.readonly()) {\n this.value.set(newValue);\n }\n }\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { DynamicTextPipe, FieldOption, ValueType } from '@ng-forge/dynamic-forms';\nimport { injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { BsRadioProps } from './bs-radio.type';\nimport { AsyncPipe } from '@angular/common';\nimport { BsRadioGroupComponent } from './bs-radio-group.component';\n\n@Component({\n selector: 'df-bs-radio',\n imports: [BsRadioGroupComponent, FormField, DynamicTextPipe, AsyncPipe],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field();\n\n <div class=\"mb-3\">\n @if (ngf.label(); as label) {\n <div class=\"form-label\">{{ label | dynamicText | async }}</div>\n }\n\n <df-bs-radio-group [formField]=\"f\" [label]=\"ngf.label()\" [options]=\"options()\" [properties]=\"props()\" />\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (props()?.hint; as hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ hint | dynamicText | async }}</div>\n }\n </div>\n `,\n styles: [\n `\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class BsRadioFieldComponent {\n protected readonly ngf = injectNgForgeField<ValueType>();\n\n readonly options = input<FieldOption<ValueType>[]>([]);\n readonly props = input<BsRadioProps>();\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { DynamicTextPipe, FieldOption } from '@ng-forge/dynamic-forms';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { BsSelectProps } from './bs-select.type';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-bs-select',\n imports: [FormField, DynamicTextPipe, AsyncPipe, NgForgeControl],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field(); @let selectId = ngf.key() + '-select';\n\n <div class=\"mb-3\">\n @if (ngf.label(); as label) {\n <label [for]=\"selectId\" class=\"form-label\">{{ label | dynamicText | async }}</label>\n }\n <select\n ngForgeControl\n [formField]=\"f\"\n [id]=\"selectId\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-select\"\n [class.form-select-sm]=\"props()?.size === 'sm'\"\n [class.form-select-lg]=\"props()?.size === 'lg'\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [multiple]=\"props()?.multiple || false\"\n [size]=\"props()?.htmlSize\"\n >\n @if (ngf.placeholder(); as placeholder) {\n <option value=\"\" disabled [selected]=\"!f().value()\">{{ placeholder | dynamicText | async }}</option>\n }\n @for (option of options(); track option.value) {\n <option [value]=\"option.value\" [disabled]=\"option.disabled || false\" [selected]=\"isSelected(option.value, f().value())\">\n {{ option.label | dynamicText | async }}\n </option>\n }\n </select>\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (props()?.hint; as hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ hint | dynamicText | async }}</div>\n }\n </div>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n styles: [\n `\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n})\nexport default class BsSelectFieldComponent {\n protected readonly ngf = injectNgForgeField<string>();\n\n readonly options = input<FieldOption<string>[]>([]);\n readonly props = input<BsSelectProps>();\n\n defaultCompare = Object.is;\n\n protected isSelected(optionValue: string, fieldValue: string | string[] | null): boolean {\n const compareWith = this.props()?.compareWith || this.defaultCompare;\n\n if (Array.isArray(fieldValue)) {\n return fieldValue.some((v) => compareWith(v, optionValue));\n }\n\n return fieldValue !== null && compareWith(fieldValue, optionValue);\n }\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { BsSliderProps } from './bs-slider.type';\nimport { AsyncPipe } from '@angular/common';\nimport { InputConstraintsDirective } from '../../directives/input-constraints.directive';\n\n@Component({\n selector: 'df-bs-slider',\n imports: [FormField, DynamicTextPipe, AsyncPipe, InputConstraintsDirective, NgForgeControl],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field(); @let inputId = ngf.key() + '-input';\n\n <div class=\"mb-3\">\n @if (ngf.label(); as label) {\n <label [for]=\"inputId\" class=\"form-label\">\n {{ label | dynamicText | async }}\n @if (props()?.showValue) {\n <span class=\"ms-2 badge bg-secondary\"> {{ props()?.valuePrefix }}{{ f().value() }}{{ props()?.valueSuffix }} </span>\n }\n </label>\n }\n\n <input\n ngForgeControl\n type=\"range\"\n dfBsInputConstraints\n [formField]=\"f\"\n [id]=\"inputId\"\n [dfMin]=\"f().min?.() ?? props()?.min ?? min()\"\n [dfMax]=\"f().max?.() ?? props()?.max ?? max()\"\n [dfStep]=\"step() ?? props()?.step ?? 1\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-range\"\n />\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (props()?.hint; as hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ hint | dynamicText | async }}</div>\n }\n </div>\n `,\n styles: [\n `\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class BsSliderFieldComponent {\n protected readonly ngf = injectNgForgeField<number>();\n\n readonly min = input<number>(0);\n readonly max = input<number>(100);\n readonly step = input<number>();\n\n readonly props = input<BsSliderProps>();\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { BsTextareaProps } from './bs-textarea.type';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-bs-textarea',\n imports: [FormField, DynamicTextPipe, AsyncPipe, NgForgeControl],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field(); @let p = props(); @let textareaId = ngf.key() + '-textarea';\n @if (p?.floatingLabel) {\n <!-- Floating label variant -->\n <div class=\"form-floating mb-3\">\n <textarea\n ngForgeControl\n [formField]=\"f\"\n [id]=\"textareaId\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-control\"\n [class.form-control-sm]=\"p?.size === 'sm'\"\n [class.form-control-lg]=\"p?.size === 'lg'\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n ></textarea>\n\n @if (ngf.label()) {\n <label [for]=\"textareaId\">{{ ngf.label() | dynamicText | async }}</label>\n }\n @if (p?.validFeedback && f().valid() && f().touched()) {\n <div class=\"valid-feedback d-block\">\n {{ p?.validFeedback | dynamicText | async }}\n </div>\n }\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (p?.hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ p?.hint | dynamicText | async }}</div>\n }\n </div>\n } @else {\n <!-- Standard variant -->\n <div class=\"mb-3\">\n @if (ngf.label()) {\n <label [for]=\"textareaId\" class=\"form-label\">{{ ngf.label() | dynamicText | async }}</label>\n }\n\n <textarea\n ngForgeControl\n [formField]=\"f\"\n [id]=\"textareaId\"\n [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n class=\"form-control\"\n [class.form-control-sm]=\"p?.size === 'sm'\"\n [class.form-control-lg]=\"p?.size === 'lg'\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n ></textarea>\n\n @if (p?.validFeedback && f().valid() && f().touched()) {\n <div class=\"valid-feedback d-block\">\n {{ p?.validFeedback | dynamicText | async }}\n </div>\n }\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (p?.hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ p?.hint | dynamicText | async }}</div>\n }\n </div>\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n styles: [\n `\n :host([hidden]) {\n display: none !important;\n }\n `,\n ],\n})\nexport default class BsTextareaFieldComponent {\n protected readonly ngf = injectNgForgeField<string>();\n\n readonly props = input<BsTextareaProps>();\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms';\nimport { NgForgeControl, injectNgForgeField, NgForgeFieldHost } from '@ng-forge/dynamic-forms/integration';\nimport { BsToggleProps } from './bs-toggle.type';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'df-bs-toggle',\n imports: [FormField, DynamicTextPipe, AsyncPipe, NgForgeControl],\n styleUrl: '../../styles/_form-field.scss',\n hostDirectives: [NgForgeFieldHost],\n template: `\n @let f = ngf.field(); @let inputId = ngf.key() + '-input';\n\n <div\n class=\"form-check form-switch\"\n [class.form-check-inline]=\"props()?.inline\"\n [class.form-check-reverse]=\"props()?.reverse\"\n [class.form-switch-sm]=\"props()?.size === 'sm'\"\n [class.form-switch-lg]=\"props()?.size === 'lg'\"\n [attr.hidden]=\"f().hidden() || null\"\n >\n <input\n ngForgeControl\n type=\"checkbox\"\n [formField]=\"f\"\n [id]=\"inputId\"\n class=\"form-check-input\"\n [class.is-invalid]=\"f().invalid() && f().touched()\"\n [attr.tabindex]=\"ngf.tabIndex()\"\n />\n <label [for]=\"inputId\" class=\"form-check-label\">\n {{ ngf.label() | dynamicText | async }}\n </label>\n </div>\n\n @if (ngf.errorsToDisplay()[0]; as error) {\n <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n } @else if (props()?.hint; as hint) {\n <div class=\"form-text\" [id]=\"ngf.hintId()\" [attr.hidden]=\"f().hidden() || null\">{{ hint | dynamicText | async }}</div>\n }\n `,\n styles: [\n `\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n /* Custom size variants for switches */\n .form-switch-sm .form-check-input {\n width: 1.75rem;\n height: 1rem;\n font-size: 0.875rem;\n }\n\n .form-switch-lg .form-check-input {\n width: 3rem;\n height: 1.75rem;\n font-size: 1.125rem;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class BsToggleFieldComponent {\n protected readonly ngf = injectNgForgeField<boolean>();\n\n readonly props = input<BsToggleProps>();\n}\n","/**\n * Bootstrap field type constants\n * Based on available field components in the /fields folder\n */\nexport const BsField = {\n Input: 'input',\n Select: 'select',\n Checkbox: 'checkbox',\n Button: 'button',\n Submit: 'submit',\n Next: 'next',\n Previous: 'previous',\n AddArrayItem: 'addArrayItem',\n PrependArrayItem: 'prependArrayItem',\n InsertArrayItem: 'insertArrayItem',\n RemoveArrayItem: 'removeArrayItem',\n PopArrayItem: 'popArrayItem',\n ShiftArrayItem: 'shiftArrayItem',\n Textarea: 'textarea',\n Radio: 'radio',\n MultiCheckbox: 'multi-checkbox',\n Datepicker: 'datepicker',\n Slider: 'slider',\n Toggle: 'toggle',\n} as const;\n\nexport type BsFieldType = (typeof BsField)[keyof typeof BsField];\n","import { computed, inject, isSignal, Signal } from '@angular/core';\nimport { ARRAY_CONTEXT, buildBaseInputs, DEFAULT_PROPS, FieldDef } from '@ng-forge/dynamic-forms';\n\n/**\n * Generic button mapper for custom events or basic buttons.\n * For specific button types (submit, next, prev, add/remove array items),\n * use the dedicated field types and their specific mappers.\n *\n * @param fieldDef The button field definition\n * @returns Signal containing Record of input names to values for ngComponentOutlet\n */\nexport function buttonFieldMapper(fieldDef: FieldDef<Record<string, unknown>>): Signal<Record<string, unknown>> {\n const defaultProps = inject(DEFAULT_PROPS);\n const arrayContext = inject(ARRAY_CONTEXT, { optional: true });\n\n return computed(() => {\n const baseInputs = buildBaseInputs(fieldDef, defaultProps());\n\n const inputs: Record<string, unknown> = {\n ...baseInputs,\n };\n\n if (fieldDef.disabled !== undefined) {\n inputs['disabled'] = fieldDef.disabled;\n }\n\n if (fieldDef.hidden !== undefined) {\n inputs['hidden'] = fieldDef.hidden;\n }\n\n // Add event binding for button events\n if ('event' in fieldDef && fieldDef.event !== undefined) {\n inputs['event'] = fieldDef.event;\n }\n\n // Add eventArgs binding if provided\n if ('eventArgs' in fieldDef && fieldDef.eventArgs !== undefined) {\n inputs['eventArgs'] = fieldDef.eventArgs;\n }\n\n // Add eventContext for token resolution (supports $template, $arrayKey, $index, etc.)\n const template = 'template' in fieldDef ? fieldDef.template : undefined;\n if (template || arrayContext) {\n // Read signal value if index is a signal (supports differential updates)\n const getIndex = () => {\n if (!arrayContext) return -1;\n return isSignal(arrayContext.index) ? arrayContext.index() : arrayContext.index;\n };\n\n inputs['eventContext'] = {\n key: fieldDef.key,\n index: getIndex(),\n arrayKey: arrayContext?.arrayKey ?? '',\n formValue: arrayContext?.formValue ?? {},\n template,\n };\n }\n\n return inputs;\n });\n}\n","import { FieldTypeDefinition } from '@ng-forge/dynamic-forms';\nimport {\n addArrayItemButtonMapper,\n checkboxFieldMapper,\n datepickerFieldMapper,\n insertArrayItemButtonMapper,\n optionsFieldMapper,\n popArrayItemButtonMapper,\n prependArrayItemButtonMapper,\n removeArrayItemButtonMapper,\n shiftArrayItemButtonMapper,\n valueFieldMapper,\n} from '@ng-forge/dynamic-forms/integration';\nimport { BsField } from '../types/types';\nimport { buttonFieldMapper } from '../fields/button/bs-button.mapper';\nimport { nextButtonFieldMapper, previousButtonFieldMapper, submitButtonFieldMapper } from '../fields/button/bs-specific-button.mapper';\n\nconst VALUE_FIELD_TYPES_BASE = {\n renderReadyWhen: ['field'],\n} as const;\n\nconst BUTTON_FIELD_TYPES_BASE = {\n renderReadyWhen: [],\n valueHandling: 'exclude',\n} as const;\n\nexport const BOOTSTRAP_FIELD_TYPES: FieldTypeDefinition[] = [\n {\n name: BsField.Input,\n loadComponent: () => import('../fields/input/bs-input.component'),\n mapper: valueFieldMapper,\n propsToMeta: ['type'],\n scope: ['text-input', 'numeric'],\n addons: {\n slots: ['prefix', 'suffix'],\n },\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Select,\n loadComponent: () => import('../fields/select/bs-select.component'),\n mapper: optionsFieldMapper,\n scope: 'single-select',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Checkbox,\n loadComponent: () => import('../fields/checkbox/bs-checkbox.component'),\n mapper: checkboxFieldMapper,\n scope: 'boolean',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Button,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: buttonFieldMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Submit,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: submitButtonFieldMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Next,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: nextButtonFieldMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Previous,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: previousButtonFieldMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.AddArrayItem,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: addArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.PrependArrayItem,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: prependArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.InsertArrayItem,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: insertArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.RemoveArrayItem,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: removeArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.PopArrayItem,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: popArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.ShiftArrayItem,\n loadComponent: () => import('../fields/button/bs-button.component'),\n mapper: shiftArrayItemButtonMapper,\n ...BUTTON_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Textarea,\n loadComponent: () => import('../fields/textarea/bs-textarea.component'),\n mapper: valueFieldMapper,\n propsToMeta: ['rows'],\n scope: 'text-input',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Radio,\n loadComponent: () => import('../fields/radio/bs-radio.component'),\n mapper: optionsFieldMapper,\n scope: 'single-select',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: BsField.MultiCheckbox,\n loadComponent: () => import('../fields/multi-checkbox/bs-multi-checkbox.component'),\n mapper: optionsFieldMapper,\n scope: 'multi-select',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Datepicker,\n loadComponent: () => import('../fields/datepicker/bs-datepicker.component'),\n mapper: datepickerFieldMapper,\n scope: 'date',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Slider,\n loadComponent: () => import('../fields/slider/bs-slider.component'),\n mapper: valueFieldMapper,\n scope: 'numeric',\n ...VALUE_FIELD_TYPES_BASE,\n },\n {\n name: BsField.Toggle,\n loadComponent: () => import('../fields/toggle/bs-toggle.component'),\n mapper: checkboxFieldMapper,\n scope: 'boolean',\n ...VALUE_FIELD_TYPES_BASE,\n },\n];\n","import type { Provider } from '@angular/core';\nimport { ADDON_KIND_DEFINITIONS, DynamicFormError, type AddonKindDefinition, type FieldTypeDefinition } from '@ng-forge/dynamic-forms';\nimport { BOOTSTRAP_FIELD_TYPES } from '../config/bootstrap-field-config';\nimport { BootstrapConfig } from '../models/bootstrap-config';\nimport { BOOTSTRAP_CONFIG } from '../models/bootstrap-config.token';\nimport type { BsButtonAddon, BsIconAddon } from '../types/addons';\n\n/** Field type definitions for Bootstrap components. */\nexport type BootstrapFieldTypes = FieldTypeDefinition[];\n\ntype BootstrapConfigFeature = {\n ɵkind: 'bootstrap-config';\n ɵproviders: Provider[];\n};\n\n/**\n * Default `withBootstrapFields()` shape — field defs + the auto-included\n * addons feature so `bs-icon` / `bs-button` work out of the box.\n */\ntype BootstrapFieldsWithAddons = [...BootstrapFieldTypes, BootstrapAddonsFeature];\n\ntype BootstrapFieldsWithConfig = [...BootstrapFieldTypes, BootstrapAddonsFeature, BootstrapConfigFeature];\n\n/**\n * Provides Bootstrap field type definitions for the dynamic form system,\n * with Bootstrap-shipped addon kinds (`bs-icon`, `bs-button`) auto-included\n * so addons work out of the box.\n *\n * @param config - Optional global configuration for Bootstrap form fields\n * @returns Tuple of field type definitions, the addons feature, and\n * optionally a config feature.\n */\nexport function withBootstrapFields(): BootstrapFieldsWithAddons;\nexport function withBootstrapFields(config: BootstrapConfig): BootstrapFieldsWithConfig;\nexport function withBootstrapFields(config: BootstrapConfig | undefined): BootstrapFieldsWithAddons | BootstrapFieldsWithConfig;\nexport function withBootstrapFields(config?: BootstrapConfig): BootstrapFieldsWithAddons | BootstrapFieldsWithConfig {\n // Always include the addons feature — bs-icon / bs-button are part of\n // the canonical Bootstrap surface.\n const base: unknown[] = [...BOOTSTRAP_FIELD_TYPES, withBootstrapAddons()];\n\n if (config) {\n base.push({\n ɵkind: 'bootstrap-config',\n ɵproviders: [{ provide: BOOTSTRAP_CONFIG, useValue: config }],\n } satisfies BootstrapConfigFeature);\n return base as BootstrapFieldsWithConfig;\n }\n\n return base as BootstrapFieldsWithAddons;\n}\n\n/* -- Bootstrap addon kinds --------------------------------------------- */\n\nconst BS_ICON_KIND: AddonKindDefinition<BsIconAddon> = {\n kind: 'bs-icon',\n loadComponent: () => import('../addons/bs-icon-addon.component').then((m) => m.BsIconAddonComponent),\n validate: (addon, fieldKey) => {\n if (typeof addon.icon !== 'string' || addon.icon.length === 0) {\n throw new DynamicFormError(`Addon kind 'bs-icon' requires a non-empty 'icon' string (field: '${fieldKey}').`);\n }\n },\n};\n\nconst BS_BUTTON_KIND: AddonKindDefinition<BsButtonAddon> = {\n kind: 'bs-button',\n loadComponent: () => import('../addons/bs-button-addon.component').then((m) => m.BsButtonAddonComponent),\n validate: (addon, fieldKey) => {\n // Exactly one of preset / actionRef / action — validator drops the addon\n // (with warning) if the rule is violated.\n const set = [addon.preset, addon.actionRef, addon.action].filter((v) => v !== undefined);\n if (set.length > 1) {\n throw new DynamicFormError(\n `Addon kind 'bs-button' on field '${fieldKey}' has more than one of preset/actionRef/action — exactly one allowed.`,\n );\n }\n // Icon-only buttons require ariaLabel for screen readers.\n if (addon.icon && !addon.label && !addon.ariaLabel) {\n throw new DynamicFormError(`Addon kind 'bs-button' on field '${fieldKey}' is icon-only — provide 'ariaLabel' for accessibility.`);\n }\n },\n};\n\n/**\n * Feature kind discriminant for the Bootstrap addons feature. Matches core's\n * `'addons'` kind so providers flow through the standard addon-kind pipeline\n * in `provideDynamicForm`.\n */\ntype BootstrapAddonsFeature = {\n ɵkind: 'addons';\n ɵproviders: Provider[];\n};\n\n/** Register Bootstrap-shipped addon kinds (`bs-icon`, `bs-button`) standalone. */\nexport function withBootstrapAddons(): BootstrapAddonsFeature {\n return {\n ɵkind: 'addons',\n ɵproviders: [\n { provide: ADDON_KIND_DEFINITIONS, useValue: BS_ICON_KIND, multi: true },\n { provide: ADDON_KIND_DEFINITIONS, useValue: BS_BUTTON_KIND, multi: true },\n ],\n };\n}\n","import { AsyncPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { DynamicTextPipe, WrapperFieldInputs } from '@ng-forge/dynamic-forms';\nimport type { BsIconAddon } from '../types/addons';\n\n/** Renderer for the `bs-icon` addon kind. */\n@Component({\n selector: 'df-bs-icon-addon',\n imports: [AsyncPipe, DynamicTextPipe],\n template: `<i [class]=\"iconClass()\" [attr.aria-label]=\"(ariaLabel() | dynamicText | async) ?? null\"></i>`,\n host: {\n '[attr.aria-hidden]': 'hasAriaLabel() ? null : \"true\"',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BsIconAddonComponent {\n readonly addon = input.required<BsIconAddon>();\n /** Accepted for contract uniformity — `NgComponentOutlet` setInput is strict; every kind must declare it. */\n readonly fieldInputs = input<WrapperFieldInputs | undefined>();\n\n protected readonly iconClass = computed(() => `bi bi-${this.addon().icon}`);\n protected readonly ariaLabel = computed(() => this.addon().ariaLabel);\n protected readonly hasAriaLabel = computed(() => this.addon().ariaLabel !== undefined);\n}\n","import { AsyncPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed } from '@angular/core';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms';\nimport { injectNgForgeAddonAction, NgForgeAddonAction } from '@ng-forge/dynamic-forms/integration';\nimport type { BsButtonAddon } from '../types/addons';\n\n/** Renderer for the `bs-button` addon kind. */\n@Component({\n selector: 'df-bs-button-addon',\n imports: [DynamicTextPipe, AsyncPipe],\n hostDirectives: [NgForgeAddonAction],\n template: `\n <button\n type=\"button\"\n [class]=\"buttonClass()\"\n [disabled]=\"action.disabled() || action.loading()\"\n [attr.aria-label]=\"(ariaLabel() | dynamicText | async) ?? null\"\n [attr.aria-busy]=\"action.loading() || null\"\n (click)=\"action.dispatch()\"\n >\n @if (action.loading()) {\n <!-- Visually-hidden role=status text gives a reliable AT announcement (VO/JAWS/NVDA). -->\n <span class=\"spinner-border spinner-border-sm\" aria-hidden=\"true\"></span>\n <span class=\"visually-hidden\" role=\"status\">Loading…</span>\n } @else if (iconClass(); as ic) {\n <i [class]=\"ic\" aria-hidden=\"true\"></i>\n }\n @if (label(); as l) {\n <span>{{ l | dynamicText | async }}</span>\n }\n </button>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BsButtonAddonComponent {\n protected readonly action = injectNgForgeAddonAction<BsButtonAddon>();\n\n /** Re-exposed for template binding — same signal stored on the directive. */\n protected readonly addon = this.action.addon;\n\n protected readonly label = computed(() => this.addon().label);\n protected readonly ariaLabel = computed(() => this.addon().ariaLabel);\n protected readonly iconClass = computed(() => {\n const icon = this.addon().icon;\n return icon ? `bi bi-${icon}` : '';\n });\n protected readonly buttonClass = computed(() => `btn btn-outline-${this.addon().severity ?? 'secondary'}`);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-forge/dynamic-forms-bootstrap",
3
- "version": "0.10.0-next.1",
3
+ "version": "0.10.0-next.3",
4
4
  "description": "Bootstrap 5 integration for @ng-forge/dynamic-forms. Pre-built Bootstrap form components.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -41,7 +41,7 @@
41
41
  "@angular/common": "~21.2.0",
42
42
  "@angular/core": "~21.2.0",
43
43
  "@angular/forms": "~21.2.0",
44
- "@ng-forge/dynamic-forms": "~0.10.0-next.1",
44
+ "@ng-forge/dynamic-forms": "~0.10.0-next.3",
45
45
  "rxjs": ">=7.0.0"
46
46
  },
47
47
  "module": "fesm2022/ng-forge-dynamic-forms-bootstrap.mjs",
@@ -14,9 +14,7 @@ interface BsButtonProps {
14
14
  type?: 'button' | 'submit' | 'reset';
15
15
  }
16
16
  type BsButtonField<TEvent extends FormEvent> = ButtonField<BsButtonProps, TEvent>;
17
- /**
18
- * Specific button field types with preconfigured events
19
- */
17
+ /** Specific button field types with preconfigured events */
20
18
  /** Submit button field - automatically disabled when form is invalid */
21
19
  type BsSubmitButtonField = Omit<BsButtonField<SubmitEvent>, 'event' | 'type' | 'eventArgs'> & {
22
20
  type: 'submit';
@@ -70,9 +68,7 @@ type InsertArrayItemButtonField = Omit<BsButtonField<InsertArrayItemEvent>, 'eve
70
68
  * When inside an array, this is automatically determined from context.
71
69
  */
72
70
  arrayKey?: string;
73
- /**
74
- * The index at which to insert the new item.
75
- */
71
+ /** The index at which to insert the new item. */
76
72
  index: number;
77
73
  /**
78
74
  * Template for the new array item. REQUIRED.
@@ -169,15 +165,7 @@ declare class BsDatepickerFieldComponent {
169
165
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<BsDatepickerFieldComponent, "df-bs-datepicker", never, { "minDate": { "alias": "minDate"; "required": false; "isSignal": true; }; "maxDate": { "alias": "maxDate"; "required": false; "isSignal": true; }; "startAt": { "alias": "startAt"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof _ng_forge_dynamic_forms_integration.NgForgeFieldHost; inputs: {}; outputs: {}; }]>;
170
166
  }
171
167
 
172
- /**
173
- * Decorative icon addon for Bootstrap fields.
174
- *
175
- * Renders `<i class="bi bi-{icon}">` (Bootstrap Icons). The `icon` string is the
176
- * bare suffix — e.g., `'search'` produces `<i class="bi bi-search">`.
177
- *
178
- * Add `ariaLabel` for icons that convey meaning (search, error, success);
179
- * leave it omitted for purely decorative icons (will be `aria-hidden="true"`).
180
- */
168
+ /** Decorative icon addon for Bootstrap fields. */
181
169
  interface BsIconAddon extends BaseAddon {
182
170
  readonly kind: 'bs-icon';
183
171
  /** Bootstrap Icons name without the `bi-` prefix (e.g., `'search'`, `'x'`). */
@@ -200,11 +188,6 @@ interface BsButtonBase extends BaseAddon {
200
188
  * Click axis — XOR enforced at type level so configurations that combine
201
189
  * two click handlers (e.g., `preset` AND `actionRef`) are rejected by
202
190
  * TypeScript. The four shapes:
203
- *
204
- * - `Preset` — built-in preset action.
205
- * - `ActionRef` — typed reference to a handler registered via `provideAddonActions(...)`.
206
- * - `Action` — inline handler (code-only; dropped from JSON-derived configs).
207
- * - `None` — decorative button with no handler.
208
191
  */
209
192
  type BsButtonClickPreset = {
210
193
  /** Built-in preset action (e.g., `'clear'`, `'toggle-password-visibility'`). JSON-safe. */
@@ -259,19 +242,7 @@ type BsButtonContentDecorative = {
259
242
  readonly ariaLabel?: DynamicText;
260
243
  };
261
244
  type BsButtonContent = BsButtonContentIconOnly | BsButtonContentLabeled | BsButtonContentDecorative;
262
- /**
263
- * Interactive button addon for Bootstrap fields.
264
- *
265
- * Renders `<button class="btn btn-outline-{severity}">` with optional icon,
266
- * label, severity, and reactive loading state.
267
- *
268
- * Type-level guarantees:
269
- *
270
- * - **Content axis (XOR):** `IconOnly` (icon + required ariaLabel) |
271
- * `Labeled` (label, icon optional) | `Decorative` (neither).
272
- * - **Click axis (XOR):** exactly one of `preset` / `actionRef` / `action`,
273
- * or none.
274
- */
245
+ /** Interactive button addon for Bootstrap fields. */
275
246
  type BsButtonAddon = BsButtonBase & BsButtonContent & BsButtonClick;
276
247
  /** Union of all Bootstrap-shipped addon kinds. */
277
248
  type BsAddon = BsIconAddon | BsButtonAddon;
@@ -294,31 +265,11 @@ interface BsInputProps extends InputProps {
294
265
  /**
295
266
  * Module-augmentable seam for adding custom addon kinds to `bs-input` at
296
267
  * the type level. Pair with `withCustomAddon(...)` for the runtime side:
297
- *
298
- * ```ts
299
- * declare module '@ng-forge/dynamic-forms-bootstrap' {
300
- * interface BsAddonExtensions {
301
- * 'my-rating': MyRatingAddon;
302
- * }
303
- * }
304
- * ```
305
- *
306
- * Empty by default — the extension lookup resolves to `never` and contributes
307
- * nothing to the union.
308
268
  */
309
269
  interface BsAddonExtensions {
310
270
  }
311
271
  type BsAddonExtension = BsAddonExtensions[keyof BsAddonExtensions];
312
- /**
313
- * Addon kinds accepted by `bs-input`.
314
- *
315
- * Bootstrap-specific kinds (`bs-icon`, `bs-button`) plus the universal `text`
316
- * and `template` kinds. `component` is permitted at runtime via the broader
317
- * `BaseAddon` union (and dropped in JSON-derived configs by the validator)
318
- * but excluded here so the IDE narrows tightly to declarative shapes.
319
- *
320
- * To extend with custom kinds, augment `BsAddonExtensions`.
321
- */
272
+ /** Addon kinds accepted by `bs-input`. */
322
273
  type BsInputAddon = BsIconAddon | BsButtonAddon | TextAddon | TemplateAddon | BsAddonExtension;
323
274
  type BsInputField = InputField<BsInputProps> & {
324
275
  addons?: ReadonlyArray<BsInputAddon>;
@@ -490,50 +441,35 @@ declare class BsToggleFieldComponent {
490
441
 
491
442
  declare const BOOTSTRAP_FIELD_TYPES: FieldTypeDefinition[];
492
443
 
493
- /**
494
- * Configuration options for Bootstrap form fields.
495
- *
496
- * These settings can be applied at two levels:
497
- * - **Library-level**: Via `withBootstrapFields({ ... })` - applies to all forms
498
- * - **Form-level**: Via `defaultProps` in form config - applies to a specific form
499
- *
500
- * The cascade hierarchy is: Library-level → Form-level → Field-level
501
- *
502
- * @example
503
- * ```typescript
504
- * // Library-level (in app config)
505
- * provideDynamicForms(withBootstrapFields({ size: 'sm', floatingLabel: true }))
506
- *
507
- * // Form-level (in form config)
508
- * const config: BsFormConfig = {
509
- * defaultProps: { size: 'lg' },
510
- * fields: [...]
511
- * };
512
- * ```
513
- */
444
+ /** Configuration options for Bootstrap form fields. */
514
445
  interface BootstrapConfig {
515
446
  /**
516
447
  * Default size for form controls
448
+ *
517
449
  * @default undefined
518
450
  */
519
451
  size?: 'sm' | 'lg';
520
452
  /**
521
453
  * Whether to use floating labels by default for inputs
454
+ *
522
455
  * @default false
523
456
  */
524
457
  floatingLabel?: boolean;
525
458
  /**
526
459
  * Default variant for buttons
460
+ *
527
461
  * @default 'primary'
528
462
  */
529
463
  variant?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'light' | 'dark' | 'link';
530
464
  /**
531
465
  * Whether buttons should be outlined by default
466
+ *
532
467
  * @default false
533
468
  */
534
469
  outline?: boolean;
535
470
  /**
536
471
  * Whether buttons should be block-level by default
472
+ *
537
473
  * @default false
538
474
  */
539
475
  block?: boolean;
@@ -542,23 +478,6 @@ interface BootstrapConfig {
542
478
  /**
543
479
  * Injection token for Bootstrap form configuration.
544
480
  * Use this to provide global configuration for Bootstrap form fields.
545
- *
546
- * @example
547
- * ```typescript
548
- * import { provideDynamicForm } from '@ng-forge/dynamic-forms';
549
- * import { withBootstrapFields } from '@ng-forge/dynamic-forms-bootstrap';
550
- *
551
- * export const appConfig: ApplicationConfig = {
552
- * providers: [
553
- * provideDynamicForm(
554
- * ...withBootstrapFields({
555
- * floatingLabel: true,
556
- * size: 'lg'
557
- * })
558
- * )
559
- * ]
560
- * };
561
- * ```
562
481
  */
563
482
  declare const BOOTSTRAP_CONFIG: InjectionToken<BootstrapConfig>;
564
483
 
@@ -589,49 +508,9 @@ declare const BsField: {
589
508
  };
590
509
  type BsFieldType = (typeof BsField)[keyof typeof BsField];
591
510
 
592
- /**
593
- * Bootstrap-specific props that can be set at form level and cascade to all fields.
594
- *
595
- * This is the same type as `BootstrapConfig` used in `withBootstrapFields()`.
596
- * Using a single type ensures consistency between library-level and form-level configuration.
597
- *
598
- * The cascade hierarchy is: Library-level → Form-level → Field-level
599
- *
600
- * @example
601
- * ```typescript
602
- * const config: BsFormConfig = {
603
- * defaultProps: {
604
- * size: 'sm',
605
- * floatingLabel: true,
606
- * },
607
- * fields: [
608
- * { type: 'bs-input', key: 'name', label: 'Name' },
609
- * ],
610
- * };
611
- * ```
612
- */
511
+ /** Bootstrap-specific props that can be set at form level and cascade to all fields. */
613
512
  type BsFormProps = BootstrapConfig;
614
- /**
615
- * Bootstrap-specific FormConfig with type-safe defaultProps.
616
- *
617
- * Use this type alias when defining form configurations with Bootstrap components
618
- * to get IDE autocomplete and type checking for `defaultProps`.
619
- *
620
- * @example
621
- * ```typescript
622
- * const formConfig: BsFormConfig = {
623
- * defaultProps: {
624
- * size: 'sm',
625
- * floatingLabel: true,
626
- * variant: 'primary',
627
- * },
628
- * fields: [
629
- * { type: 'bs-input', key: 'name', label: 'Name' }, // Uses form defaultProps
630
- * { type: 'bs-input', key: 'email', props: { size: 'lg' } }, // Override
631
- * ],
632
- * };
633
- * ```
634
- */
513
+ /** Bootstrap-specific FormConfig with type-safe defaultProps. */
635
514
  type BsFormConfig<TFields extends NarrowFields | RegisteredFieldTypes[] = RegisteredFieldTypes[], TValue = InferFormValue<TFields extends readonly RegisteredFieldTypes[] ? TFields : RegisteredFieldTypes[]>> = FormConfig<TFields, TValue, BsFormProps>;
636
515
 
637
516
  /**
@@ -664,9 +543,7 @@ declare module '@ng-forge/dynamic-forms' {
664
543
  }
665
544
  }
666
545
 
667
- /**
668
- * Field type definitions for Bootstrap components.
669
- */
546
+ /** Field type definitions for Bootstrap components. */
670
547
  type BootstrapFieldTypes = FieldTypeDefinition[];
671
548
  type BootstrapConfigFeature = {
672
549
  ɵkind: 'bootstrap-config';
@@ -683,40 +560,7 @@ type BootstrapFieldsWithConfig = [...BootstrapFieldTypes, BootstrapAddonsFeature
683
560
  * with Bootstrap-shipped addon kinds (`bs-icon`, `bs-button`) auto-included
684
561
  * so addons work out of the box.
685
562
  *
686
- * If you want addons WITHOUT the field types (rare — e.g., adding addons to
687
- * a form that uses custom fields), call `withBootstrapAddons()` standalone.
688
- *
689
563
  * @param config - Optional global configuration for Bootstrap form fields
690
- *
691
- * @example
692
- * ```typescript
693
- * // Application-level setup — addons (bs-icon, bs-button) ship in automatically
694
- * import { ApplicationConfig } from '@angular/core';
695
- * import { provideDynamicForm } from '@ng-forge/dynamic-forms';
696
- * import { withBootstrapFields } from '@ng-forge/dynamic-forms-bootstrap';
697
- *
698
- * export const appConfig: ApplicationConfig = {
699
- * providers: [
700
- * provideDynamicForm(...withBootstrapFields())
701
- * ]
702
- * };
703
- * ```
704
- *
705
- * @example
706
- * ```typescript
707
- * // With global configuration
708
- * export const appConfig: ApplicationConfig = {
709
- * providers: [
710
- * provideDynamicForm(
711
- * ...withBootstrapFields({
712
- * floatingLabel: true,
713
- * size: 'lg'
714
- * })
715
- * )
716
- * ]
717
- * };
718
- * ```
719
- *
720
564
  * @returns Tuple of field type definitions, the addons feature, and
721
565
  * optionally a config feature.
722
566
  */
@@ -732,36 +576,10 @@ type BootstrapAddonsFeature = {
732
576
  ɵkind: 'addons';
733
577
  ɵproviders: Provider[];
734
578
  };
735
- /**
736
- * Register Bootstrap-shipped addon kinds (`bs-icon`, `bs-button`) standalone.
737
- *
738
- * **Most users don't need this** — `withBootstrapFields()` auto-includes
739
- * these kinds. Call `withBootstrapAddons()` directly only when you want
740
- * Bootstrap addon kinds without the Bootstrap field types (e.g., a custom
741
- * field set that wants to render `bs-icon` prefixes), or when you're
742
- * stitching addons through a different DI scope.
743
- *
744
- * @example
745
- * ```typescript
746
- * // Custom field types + Bootstrap addon kinds.
747
- * provideDynamicForm(
748
- * ...myCustomFields(),
749
- * withBootstrapAddons(),
750
- * );
751
- * ```
752
- *
753
- * Adapter authors who need to override a kind with a customised renderer
754
- * should call `withCustomAddon(...)` directly instead.
755
- */
579
+ /** Register Bootstrap-shipped addon kinds (`bs-icon`, `bs-button`) standalone. */
756
580
  declare function withBootstrapAddons(): BootstrapAddonsFeature;
757
581
 
758
- /**
759
- * Renderer for the `bs-icon` addon kind.
760
- *
761
- * Outputs `<i class="bi bi-{icon}">`. The host is set `aria-hidden="true"`
762
- * by default; if the addon supplies an `ariaLabel`, it is applied so the
763
- * icon is announced by screen readers.
764
- */
582
+ /** Renderer for the `bs-icon` addon kind. */
765
583
  declare class BsIconAddonComponent {
766
584
  readonly addon: _angular_core.InputSignal<BsIconAddon>;
767
585
  /** Accepted for contract uniformity — `NgComponentOutlet` setInput is strict; every kind must declare it. */
@@ -773,14 +591,7 @@ declare class BsIconAddonComponent {
773
591
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<BsIconAddonComponent, "df-bs-icon-addon", never, { "addon": { "alias": "addon"; "required": true; "isSignal": true; }; "fieldInputs": { "alias": "fieldInputs"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
774
592
  }
775
593
 
776
- /**
777
- * Renderer for the `bs-button` addon kind.
778
- *
779
- * Renders a Bootstrap `btn-outline-{severity}` button. Click dispatch
780
- * (preset / actionRef / action precedence, multi-set warning, `disabled` /
781
- * `loading` resolution) lives on `NgForgeAddonAction`; this component
782
- * focuses on the visual layer.
783
- */
594
+ /** Renderer for the `bs-button` addon kind. */
784
595
  declare class BsButtonAddonComponent {
785
596
  protected readonly action: _ng_forge_dynamic_forms_integration.TypedNgForgeAddonAction<BsButtonAddon>;
786
597
  /** Re-exposed for template binding — same signal stored on the directive. */
@@ -793,17 +604,7 @@ declare class BsButtonAddonComponent {
793
604
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<BsButtonAddonComponent, "df-bs-button-addon", never, {}, {}, never, never, true, [{ directive: typeof _ng_forge_dynamic_forms_integration.NgForgeAddonAction; inputs: {}; outputs: {}; }]>;
794
605
  }
795
606
 
796
- /**
797
- * Per-field writable signal that overrides the input's `type` attribute.
798
- *
799
- * Provided at the `bs-input` field component level. The button addon's
800
- * `'toggle-password-visibility'` preset writes to it; the field component
801
- * reads it to compute its effective `type`.
802
- *
803
- * Optional from a button's perspective — when the button is hosted inside a
804
- * field that doesn't provide this token (e.g., textarea or a future
805
- * non-input field), the toggle preset is a no-op.
806
- */
607
+ /** Per-field writable signal that overrides the input's `type` attribute. */
807
608
  declare const BS_INPUT_TYPE_OVERRIDE: InjectionToken<WritableSignal<string | undefined>>;
808
609
 
809
610
  export { BOOTSTRAP_CONFIG, BOOTSTRAP_FIELD_TYPES, BS_INPUT_TYPE_OVERRIDE, BsButtonAddonComponent, BsButtonFieldComponent, BsCheckboxFieldComponent, BsDatepickerFieldComponent, BsField, BsIconAddonComponent, BsInputFieldComponent, BsMultiCheckboxFieldComponent, BsRadioFieldComponent, BsSelectFieldComponent, BsSliderFieldComponent, BsTextareaFieldComponent, BsToggleFieldComponent, withBootstrapAddons, withBootstrapFields };