@ng-primitives/mcp 0.124.0 → 0.125.0
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.
package/package.json
CHANGED
|
@@ -862,6 +862,16 @@
|
|
|
862
862
|
"inputs": [],
|
|
863
863
|
"outputs": []
|
|
864
864
|
},
|
|
865
|
+
"NgpDatePickerCell": {
|
|
866
|
+
"name": "NgpDatePickerCell",
|
|
867
|
+
"description": "A cell in the date picker grid.",
|
|
868
|
+
"selector": "[ngpDatePickerCell]",
|
|
869
|
+
"exportAs": [
|
|
870
|
+
"ngpDatePickerCell"
|
|
871
|
+
],
|
|
872
|
+
"inputs": [],
|
|
873
|
+
"outputs": []
|
|
874
|
+
},
|
|
865
875
|
"NgpDatePickerLabel": {
|
|
866
876
|
"name": "NgpDatePickerLabel",
|
|
867
877
|
"description": "The label that displays the current month and year typically in the header of the date picker. This will be announced by screen readers when the date changes.",
|
|
@@ -880,16 +890,6 @@
|
|
|
880
890
|
],
|
|
881
891
|
"outputs": []
|
|
882
892
|
},
|
|
883
|
-
"NgpDatePickerCell": {
|
|
884
|
-
"name": "NgpDatePickerCell",
|
|
885
|
-
"description": "A cell in the date picker grid.",
|
|
886
|
-
"selector": "[ngpDatePickerCell]",
|
|
887
|
-
"exportAs": [
|
|
888
|
-
"ngpDatePickerCell"
|
|
889
|
-
],
|
|
890
|
-
"inputs": [],
|
|
891
|
-
"outputs": []
|
|
892
|
-
},
|
|
893
893
|
"NgpDatePickerNextMonth": {
|
|
894
894
|
"name": "NgpDatePickerNextMonth",
|
|
895
895
|
"description": "A button that navigates to the next month.",
|
|
@@ -1439,7 +1439,7 @@
|
|
|
1439
1439
|
{
|
|
1440
1440
|
"name": "ngpInputOtpValue",
|
|
1441
1441
|
"type": "string",
|
|
1442
|
-
"description": "The current value of the OTP.",
|
|
1442
|
+
"description": "The current value of the OTP. A null/undefined value (e.g. from a form\n`writeValue(null)` or `reset()`) is coerced to an empty string.",
|
|
1443
1443
|
"isRequired": false,
|
|
1444
1444
|
"defaultValue": "''"
|
|
1445
1445
|
},
|
|
@@ -3222,133 +3222,133 @@
|
|
|
3222
3222
|
}
|
|
3223
3223
|
]
|
|
3224
3224
|
},
|
|
3225
|
-
"
|
|
3226
|
-
"name": "
|
|
3227
|
-
"description": "Apply the `
|
|
3228
|
-
"selector": "[
|
|
3225
|
+
"NgpRangeSlider": {
|
|
3226
|
+
"name": "NgpRangeSlider",
|
|
3227
|
+
"description": "Apply the `ngpRangeSlider` directive to an element that represents the range slider and contains the track, range, and thumbs.",
|
|
3228
|
+
"selector": "[ngpRangeSlider]",
|
|
3229
3229
|
"exportAs": [
|
|
3230
|
-
"
|
|
3230
|
+
"ngpRangeSlider"
|
|
3231
3231
|
],
|
|
3232
3232
|
"inputs": [
|
|
3233
3233
|
{
|
|
3234
|
-
"name": "
|
|
3234
|
+
"name": "ngpRangeSliderLow",
|
|
3235
3235
|
"type": "number",
|
|
3236
|
-
"description": "The value of the slider.",
|
|
3236
|
+
"description": "The low value of the range slider.",
|
|
3237
3237
|
"isRequired": false,
|
|
3238
3238
|
"defaultValue": "0"
|
|
3239
3239
|
},
|
|
3240
3240
|
{
|
|
3241
|
-
"name": "
|
|
3241
|
+
"name": "ngpRangeSliderHigh",
|
|
3242
3242
|
"type": "number",
|
|
3243
|
-
"description": "The
|
|
3243
|
+
"description": "The high value of the range slider.",
|
|
3244
|
+
"isRequired": false,
|
|
3245
|
+
"defaultValue": "100"
|
|
3246
|
+
},
|
|
3247
|
+
{
|
|
3248
|
+
"name": "ngpRangeSliderMin",
|
|
3249
|
+
"type": "number",
|
|
3250
|
+
"description": "The minimum value of the range slider.",
|
|
3244
3251
|
"isRequired": false,
|
|
3245
3252
|
"defaultValue": "0"
|
|
3246
3253
|
},
|
|
3247
3254
|
{
|
|
3248
|
-
"name": "
|
|
3255
|
+
"name": "ngpRangeSliderMax",
|
|
3249
3256
|
"type": "number",
|
|
3250
|
-
"description": "The maximum value of the slider.",
|
|
3257
|
+
"description": "The maximum value of the range slider.",
|
|
3251
3258
|
"isRequired": false,
|
|
3252
3259
|
"defaultValue": "100"
|
|
3253
3260
|
},
|
|
3254
3261
|
{
|
|
3255
|
-
"name": "
|
|
3262
|
+
"name": "ngpRangeSliderStep",
|
|
3256
3263
|
"type": "number",
|
|
3257
|
-
"description": "The step value of the slider.",
|
|
3264
|
+
"description": "The step value of the range slider.",
|
|
3258
3265
|
"isRequired": false,
|
|
3259
3266
|
"defaultValue": "1"
|
|
3260
3267
|
},
|
|
3261
3268
|
{
|
|
3262
|
-
"name": "
|
|
3269
|
+
"name": "ngpRangeSliderOrientation",
|
|
3263
3270
|
"type": "'horizontal' | 'vertical'",
|
|
3264
|
-
"description": "The orientation of the slider.",
|
|
3271
|
+
"description": "The orientation of the range slider.",
|
|
3265
3272
|
"isRequired": false,
|
|
3266
3273
|
"defaultValue": "'horizontal'"
|
|
3267
3274
|
},
|
|
3268
3275
|
{
|
|
3269
|
-
"name": "
|
|
3276
|
+
"name": "ngpRangeSliderDisabled",
|
|
3270
3277
|
"type": "boolean",
|
|
3271
|
-
"description": "The disabled state of the slider.",
|
|
3278
|
+
"description": "The disabled state of the range slider.",
|
|
3272
3279
|
"isRequired": false,
|
|
3273
3280
|
"defaultValue": "false"
|
|
3274
3281
|
}
|
|
3275
3282
|
],
|
|
3276
3283
|
"outputs": [
|
|
3277
3284
|
{
|
|
3278
|
-
"name": "
|
|
3285
|
+
"name": "ngpRangeSliderLowChange",
|
|
3279
3286
|
"type": "number",
|
|
3280
|
-
"description": "Emits when the value changes."
|
|
3287
|
+
"description": "Emits when the low value changes."
|
|
3288
|
+
},
|
|
3289
|
+
{
|
|
3290
|
+
"name": "ngpRangeSliderHighChange",
|
|
3291
|
+
"type": "number",
|
|
3292
|
+
"description": "Emits when the high value changes."
|
|
3281
3293
|
}
|
|
3282
3294
|
]
|
|
3283
3295
|
},
|
|
3284
|
-
"
|
|
3285
|
-
"name": "
|
|
3286
|
-
"description": "Apply the `
|
|
3287
|
-
"selector": "[
|
|
3296
|
+
"NgpSlider": {
|
|
3297
|
+
"name": "NgpSlider",
|
|
3298
|
+
"description": "Apply the `ngpSlider` directive to an element that represents the slider and contains the track, range, and thumb.",
|
|
3299
|
+
"selector": "[ngpSlider]",
|
|
3288
3300
|
"exportAs": [
|
|
3289
|
-
"
|
|
3301
|
+
"ngpSlider"
|
|
3290
3302
|
],
|
|
3291
3303
|
"inputs": [
|
|
3292
3304
|
{
|
|
3293
|
-
"name": "
|
|
3305
|
+
"name": "ngpSliderValue",
|
|
3294
3306
|
"type": "number",
|
|
3295
|
-
"description": "The
|
|
3307
|
+
"description": "The value of the slider.",
|
|
3296
3308
|
"isRequired": false,
|
|
3297
3309
|
"defaultValue": "0"
|
|
3298
3310
|
},
|
|
3299
3311
|
{
|
|
3300
|
-
"name": "
|
|
3301
|
-
"type": "number",
|
|
3302
|
-
"description": "The high value of the range slider.",
|
|
3303
|
-
"isRequired": false,
|
|
3304
|
-
"defaultValue": "100"
|
|
3305
|
-
},
|
|
3306
|
-
{
|
|
3307
|
-
"name": "ngpRangeSliderMin",
|
|
3312
|
+
"name": "ngpSliderMin",
|
|
3308
3313
|
"type": "number",
|
|
3309
|
-
"description": "The minimum value of the
|
|
3314
|
+
"description": "The minimum value of the slider.",
|
|
3310
3315
|
"isRequired": false,
|
|
3311
3316
|
"defaultValue": "0"
|
|
3312
3317
|
},
|
|
3313
3318
|
{
|
|
3314
|
-
"name": "
|
|
3319
|
+
"name": "ngpSliderMax",
|
|
3315
3320
|
"type": "number",
|
|
3316
|
-
"description": "The maximum value of the
|
|
3321
|
+
"description": "The maximum value of the slider.",
|
|
3317
3322
|
"isRequired": false,
|
|
3318
3323
|
"defaultValue": "100"
|
|
3319
3324
|
},
|
|
3320
3325
|
{
|
|
3321
|
-
"name": "
|
|
3326
|
+
"name": "ngpSliderStep",
|
|
3322
3327
|
"type": "number",
|
|
3323
|
-
"description": "The step value of the
|
|
3328
|
+
"description": "The step value of the slider.",
|
|
3324
3329
|
"isRequired": false,
|
|
3325
3330
|
"defaultValue": "1"
|
|
3326
3331
|
},
|
|
3327
3332
|
{
|
|
3328
|
-
"name": "
|
|
3333
|
+
"name": "ngpSliderOrientation",
|
|
3329
3334
|
"type": "'horizontal' | 'vertical'",
|
|
3330
|
-
"description": "The orientation of the
|
|
3335
|
+
"description": "The orientation of the slider.",
|
|
3331
3336
|
"isRequired": false,
|
|
3332
3337
|
"defaultValue": "'horizontal'"
|
|
3333
3338
|
},
|
|
3334
3339
|
{
|
|
3335
|
-
"name": "
|
|
3340
|
+
"name": "ngpSliderDisabled",
|
|
3336
3341
|
"type": "boolean",
|
|
3337
|
-
"description": "The disabled state of the
|
|
3342
|
+
"description": "The disabled state of the slider.",
|
|
3338
3343
|
"isRequired": false,
|
|
3339
3344
|
"defaultValue": "false"
|
|
3340
3345
|
}
|
|
3341
3346
|
],
|
|
3342
3347
|
"outputs": [
|
|
3343
3348
|
{
|
|
3344
|
-
"name": "
|
|
3345
|
-
"type": "number",
|
|
3346
|
-
"description": "Emits when the low value changes."
|
|
3347
|
-
},
|
|
3348
|
-
{
|
|
3349
|
-
"name": "ngpRangeSliderHighChange",
|
|
3349
|
+
"name": "ngpSliderValueChange",
|
|
3350
3350
|
"type": "number",
|
|
3351
|
-
"description": "Emits when the
|
|
3351
|
+
"description": "Emits when the value changes."
|
|
3352
3352
|
}
|
|
3353
3353
|
]
|
|
3354
3354
|
},
|
|
@@ -3381,6 +3381,13 @@
|
|
|
3381
3381
|
"description": "Determine if the switch is disabled.\n@default false",
|
|
3382
3382
|
"isRequired": false,
|
|
3383
3383
|
"defaultValue": "false"
|
|
3384
|
+
},
|
|
3385
|
+
{
|
|
3386
|
+
"name": "ngpSwitchRequired",
|
|
3387
|
+
"type": "boolean",
|
|
3388
|
+
"description": "Whether the switch is required.\n@default false",
|
|
3389
|
+
"isRequired": false,
|
|
3390
|
+
"defaultValue": "false"
|
|
3384
3391
|
}
|
|
3385
3392
|
],
|
|
3386
3393
|
"outputs": [
|
|
@@ -3469,6 +3476,13 @@
|
|
|
3469
3476
|
"description": "Whether tabs should activate on focus",
|
|
3470
3477
|
"isRequired": false,
|
|
3471
3478
|
"defaultValue": "true"
|
|
3479
|
+
},
|
|
3480
|
+
{
|
|
3481
|
+
"name": "ngpTabsetWrap",
|
|
3482
|
+
"type": "boolean",
|
|
3483
|
+
"description": "Whether keyboard focus should wrap around the tab list.\n@default true (from the global tabs config)",
|
|
3484
|
+
"isRequired": false,
|
|
3485
|
+
"defaultValue": "true"
|
|
3472
3486
|
}
|
|
3473
3487
|
],
|
|
3474
3488
|
"outputs": [
|
|
@@ -3553,7 +3567,7 @@
|
|
|
3553
3567
|
"inputs": [
|
|
3554
3568
|
{
|
|
3555
3569
|
"name": "ngpToggleGroupItemValue",
|
|
3556
|
-
"type": "
|
|
3570
|
+
"type": "T | undefined",
|
|
3557
3571
|
"description": "The value of the item.",
|
|
3558
3572
|
"isRequired": true
|
|
3559
3573
|
},
|
|
@@ -3605,17 +3619,23 @@
|
|
|
3605
3619
|
},
|
|
3606
3620
|
{
|
|
3607
3621
|
"name": "ngpToggleGroupValue",
|
|
3608
|
-
"type": "
|
|
3622
|
+
"type": "T[] | undefined",
|
|
3609
3623
|
"description": "The selected value(s) of the toggle group.",
|
|
3610
3624
|
"isRequired": false
|
|
3611
3625
|
},
|
|
3612
3626
|
{
|
|
3613
3627
|
"name": "ngpToggleGroupDefaultValue",
|
|
3614
|
-
"type": "
|
|
3628
|
+
"type": "T[]",
|
|
3615
3629
|
"description": "The default selected value(s) for uncontrolled usage.\n@default []",
|
|
3616
3630
|
"isRequired": false,
|
|
3617
3631
|
"defaultValue": "[]"
|
|
3618
3632
|
},
|
|
3633
|
+
{
|
|
3634
|
+
"name": "ngpToggleGroupCompareWith",
|
|
3635
|
+
"type": "(a: T, b: T) => boolean",
|
|
3636
|
+
"description": "The comparator used to determine whether two values are equal.\nUseful when values are objects and equality should be checked by value rather than by reference.\n@default (a, b) => a === b",
|
|
3637
|
+
"isRequired": false
|
|
3638
|
+
},
|
|
3619
3639
|
{
|
|
3620
3640
|
"name": "ngpToggleGroupDisabled",
|
|
3621
3641
|
"type": "boolean",
|
|
@@ -3627,7 +3647,7 @@
|
|
|
3627
3647
|
"outputs": [
|
|
3628
3648
|
{
|
|
3629
3649
|
"name": "ngpToggleGroupValueChange",
|
|
3630
|
-
"type": "
|
|
3650
|
+
"type": "T[]",
|
|
3631
3651
|
"description": "Emits when the value of the toggle group changes."
|
|
3632
3652
|
}
|
|
3633
3653
|
]
|
|
@@ -311,7 +311,7 @@
|
|
|
311
311
|
}
|
|
312
312
|
],
|
|
313
313
|
"reusableComponent": {
|
|
314
|
-
"code": "import { Component } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroCheckMini, heroMinusMini } from '@ng-icons/heroicons/mini';\nimport { injectCheckboxState, NgpCheckbox } from 'ng-primitives/checkbox';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-checkbox',\n hostDirectives: [\n {\n directive: NgpCheckbox,\n inputs: [\n 'ngpCheckboxChecked:checked',\n 'ngpCheckboxIndeterminate:indeterminate',\n 'ngpCheckboxDisabled:disabled',\n ],\n outputs: [\n 'ngpCheckboxCheckedChange:checkedChange',\n 'ngpCheckboxIndeterminateChange:indeterminateChange',\n ],\n },\n ],\n providers: [provideValueAccessor(Checkbox), provideIcons({ heroCheckMini, heroMinusMini })],\n imports: [NgIcon],\n template: `\n @if (state().indeterminate()) {\n <ng-icon name=\"heroMinusMini\" />\n } @else if (state().checked()) {\n <ng-icon name=\"heroCheckMini\" />\n }\n `,\n styles: `\n :host {\n display: flex;\n width: 1.25rem;\n height: 1.25rem;\n cursor: pointer;\n align-items: center;\n justify-content: center;\n border-radius: 0.25rem;\n border: 1px solid var(--ngp-border);\n background-color: transparent;\n padding: 0;\n outline: none;\n flex: none;\n color: var(--ngp-text-inverse);\n font-size: 0.75rem;\n }\n\n :host[data-hover] {\n background-color: var(--ngp-background-hover);\n }\n\n :host[data-checked],\n :host[data-indeterminate] {\n border-color: var(--ngp-background-inverse);\n background-color: var(--ngp-background-inverse);\n }\n\n :host[data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 2px;\n }\n `,\n host: {\n '(focusout)': 'onTouchedFn?.()',\n },\n})\nexport class Checkbox implements ControlValueAccessor {\n /**\n * The checked state of the checkbox.\n */\n protected readonly state = injectCheckboxState();\n\n /**\n * The onChange function for the checkbox.\n */\n protected onChangeFn?: ChangeFn<boolean>;\n\n /**\n * The onTouched function for the checkbox.\n */\n protected onTouchedFn?: TouchedFn;\n\n constructor() {\n // Whenever the user interacts with the checkbox, call the onChange function with the new value.\n this.state()\n .checkedChange.pipe(takeUntilDestroyed())\n .subscribe(checked => this.onChangeFn?.(checked));\n }\n\n writeValue(checked: boolean): void {\n this.state().setChecked(checked);\n }\n\n registerOnChange(fn: ChangeFn<boolean>): void {\n this.onChangeFn = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouchedFn = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.state().setDisabled(isDisabled);\n }\n}\n",
|
|
314
|
+
"code": "import { Component } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroCheckMini, heroMinusMini } from '@ng-icons/heroicons/mini';\nimport { injectCheckboxState, NgpCheckbox } from 'ng-primitives/checkbox';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-checkbox',\n hostDirectives: [\n {\n directive: NgpCheckbox,\n inputs: [\n 'ngpCheckboxChecked:checked',\n 'ngpCheckboxIndeterminate:indeterminate',\n 'ngpCheckboxDisabled:disabled',\n ],\n outputs: [\n 'ngpCheckboxCheckedChange:checkedChange',\n 'ngpCheckboxIndeterminateChange:indeterminateChange',\n ],\n },\n ],\n providers: [provideValueAccessor(Checkbox), provideIcons({ heroCheckMini, heroMinusMini })],\n imports: [NgIcon],\n template: `\n @if (state().indeterminate()) {\n <ng-icon name=\"heroMinusMini\" />\n } @else if (state().checked()) {\n <ng-icon name=\"heroCheckMini\" />\n }\n `,\n styles: `\n :host {\n display: flex;\n width: 1.25rem;\n height: 1.25rem;\n cursor: pointer;\n align-items: center;\n justify-content: center;\n border-radius: 0.25rem;\n border: 1px solid var(--ngp-border);\n background-color: transparent;\n padding: 0;\n outline: none;\n flex: none;\n color: var(--ngp-text-inverse);\n font-size: 0.75rem;\n }\n\n :host[data-hover] {\n background-color: var(--ngp-background-hover);\n }\n\n :host[data-checked],\n :host[data-indeterminate] {\n border-color: var(--ngp-background-inverse);\n background-color: var(--ngp-background-inverse);\n }\n\n :host[data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 2px;\n }\n `,\n host: {\n '(focusout)': 'onTouchedFn?.()',\n },\n})\nexport class Checkbox implements ControlValueAccessor {\n /**\n * The checked state of the checkbox.\n */\n protected readonly state = injectCheckboxState();\n\n /**\n * The onChange function for the checkbox.\n */\n protected onChangeFn?: ChangeFn<boolean>;\n\n /**\n * The onTouched function for the checkbox.\n */\n protected onTouchedFn?: TouchedFn;\n\n constructor() {\n // Whenever the user interacts with the checkbox, call the onChange function with the new value.\n this.state()\n .checkedChange.pipe(takeUntilDestroyed())\n .subscribe(checked => this.onChangeFn?.(checked));\n }\n\n writeValue(checked: boolean): void {\n // writing a value from the model must not re-emit through onChange\n this.state().setChecked(checked, { emit: false });\n }\n\n registerOnChange(fn: ChangeFn<boolean>): void {\n this.onChangeFn = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouchedFn = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.state().setDisabled(isDisabled);\n }\n}\n",
|
|
315
315
|
"hasVariants": false,
|
|
316
316
|
"hasSizes": true
|
|
317
317
|
}
|
|
@@ -373,7 +373,7 @@
|
|
|
373
373
|
}
|
|
374
374
|
],
|
|
375
375
|
"reusableComponent": {
|
|
376
|
-
"code": "import { BooleanInput } from '@angular/cdk/coercion';\nimport { booleanAttribute, Component, computed, input, model, signal } from '@angular/core';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroChevronDown } from '@ng-icons/heroicons/outline';\nimport {\n NgpCombobox,\n NgpComboboxButton,\n NgpComboboxDropdown,\n NgpComboboxInput,\n NgpComboboxOption,\n NgpComboboxPortal,\n} from 'ng-primitives/combobox';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-combobox',\n imports: [\n NgpCombobox,\n NgpComboboxDropdown,\n NgpComboboxOption,\n NgpComboboxInput,\n NgpComboboxPortal,\n NgpComboboxButton,\n NgIcon,\n ],\n providers: [provideIcons({ heroChevronDown }), provideValueAccessor(Combobox)],\n template: `\n <div\n [(ngpComboboxValue)]=\"value\"\n [ngpComboboxDisabled]=\"disabled() || formDisabled()\"\n (ngpComboboxOpenChange)=\"resetOnClose($event)\"\n (ngpComboboxValueChange)=\"onValueChange($event)\"\n ngpCombobox\n >\n <input\n [value]=\"filter()\"\n [placeholder]=\"placeholder()\"\n (input)=\"onFilterChange($event)\"\n (blur)=\"onTouched?.()\"\n ngpComboboxInput\n />\n\n <button ngpComboboxButton aria-label=\"Toggle dropdown\">\n <ng-icon name=\"heroChevronDown\" />\n </button>\n\n <div *ngpComboboxPortal ngpComboboxDropdown>\n @for (option of filteredOptions(); track option) {\n <div [ngpComboboxOptionValue]=\"option\" ngpComboboxOption>\n {{ option }}\n </div>\n } @empty {\n <div class=\"empty-message\">No options found</div>\n }\n </div>\n </div>\n `,\n styles: `\n [ngpCombobox] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n height: 36px;\n width: 300px;\n border-radius: 8px;\n border: none;\n background-color: var(--ngp-background);\n box-shadow: var(--ngp-input-shadow);\n box-sizing: border-box;\n }\n\n [ngpCombobox][data-focus] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 2px;\n }\n\n [ngpComboboxInput] {\n flex: 1;\n padding: 0 16px;\n border: none;\n background-color: transparent;\n color: var(--ngp-text);\n font-family: inherit;\n font-size: 14px;\n padding: 0 16px;\n outline: none;\n height: 100%;\n }\n\n [ngpComboboxButton] {\n display: inline-flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n width: 36px;\n background-color: transparent;\n border: none;\n color: var(--ngp-text);\n cursor: pointer;\n box-sizing: border-box;\n }\n\n [ngpComboboxDropdown] {\n background-color: var(--ngp-background);\n border: 1px solid var(--ngp-border);\n padding: 0.25rem;\n border-radius: 0.75rem;\n outline: none;\n position: absolute;\n animation: popover-show 0.1s ease-out;\n width: var(--ngp-combobox-width);\n box-shadow: var(--ngp-shadow-lg);\n box-sizing: border-box;\n margin-top: 4px;\n max-height: 240px;\n overflow-y: auto;\n transform-origin: var(--ngp-combobox-transform-origin);\n }\n\n [ngpComboboxDropdown][data-enter] {\n animation: combobox-show 0.1s ease-out;\n }\n\n [ngpComboboxDropdown][data-exit] {\n animation: combobox-hide 0.1s ease-out;\n }\n\n [ngpComboboxOption] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.375rem 0.75rem;\n cursor: pointer;\n border-radius: 0.5rem;\n width: 100%;\n height: 36px;\n font-size: 14px;\n color: var(--ngp-text-primary);\n box-sizing: border-box;\n }\n\n [ngpComboboxOption][data-hover] {\n background-color: var(--ngp-background-hover);\n }\n\n [ngpComboboxOption][data-press] {\n background-color: var(--ngp-background-active);\n }\n\n [ngpComboboxOption][data-active] {\n background-color: var(--ngp-background-active);\n }\n\n .empty-message {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0.5rem;\n color: var(--ngp-text-secondary);\n font-size: 14px;\n font-weight: 500;\n text-align: center;\n }\n\n @keyframes combobox-show {\n 0% {\n opacity: 0;\n transform: translateY(-10px) scale(0.9);\n }\n 100% {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n }\n\n @keyframes combobox-hide {\n 0% {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n 100% {\n opacity: 0;\n transform: translateY(-10px) scale(0.9);\n }\n }\n `,\n})\nexport class Combobox implements ControlValueAccessor {\n /** The options for the combobox. */\n readonly options = input<string[]>([]);\n\n /** The selected value. */\n readonly value = model<string | undefined>();\n\n /** The placeholder for the input. */\n readonly placeholder = input<string>('');\n\n /** The disabled state of the combobox. */\n readonly disabled = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** The filter value. */\n protected readonly filter = signal<string>('');\n\n /** Get the filtered options. */\n protected readonly filteredOptions = computed(() =>\n this.options().filter(option => option.toLowerCase().includes(this.filter().toLowerCase())),\n );\n\n /** Store the form disabled state */\n protected readonly formDisabled = signal(false);\n\n /** The on change callback */\n private onChange?: ChangeFn<string>;\n\n /** The on touch callback */\n protected onTouched?: TouchedFn;\n\n onFilterChange(event: Event): void {\n const input = event.target as HTMLInputElement;\n this.filter.set(input.value);\n }\n\n writeValue(value: string | undefined): void {\n this.value.set(value);\n this.filter.set(value ?? '');\n }\n\n registerOnChange(fn: ChangeFn<string | undefined>): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.formDisabled.set(isDisabled);\n }\n\n protected onValueChange(value: string): void {\n this.onChange?.(value);\n // update the filter value\n this.filter.set(value);\n }\n\n protected resetOnClose(open: boolean): void {\n // if the dropdown is closed, reset the filter value\n if (open) {\n return;\n }\n\n // if the filter value is empty,
|
|
376
|
+
"code": "import { BooleanInput } from '@angular/cdk/coercion';\nimport { booleanAttribute, Component, computed, input, model, signal } from '@angular/core';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroChevronDown } from '@ng-icons/heroicons/outline';\nimport {\n NgpCombobox,\n NgpComboboxButton,\n NgpComboboxDropdown,\n NgpComboboxInput,\n NgpComboboxOption,\n NgpComboboxPortal,\n} from 'ng-primitives/combobox';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-combobox',\n imports: [\n NgpCombobox,\n NgpComboboxDropdown,\n NgpComboboxOption,\n NgpComboboxInput,\n NgpComboboxPortal,\n NgpComboboxButton,\n NgIcon,\n ],\n providers: [provideIcons({ heroChevronDown }), provideValueAccessor(Combobox)],\n template: `\n <div\n [(ngpComboboxValue)]=\"value\"\n [ngpComboboxDisabled]=\"disabled() || formDisabled()\"\n (ngpComboboxOpenChange)=\"resetOnClose($event)\"\n (ngpComboboxValueChange)=\"onValueChange($event)\"\n ngpCombobox\n >\n <input\n [value]=\"filter()\"\n [placeholder]=\"placeholder()\"\n (input)=\"onFilterChange($event)\"\n (blur)=\"onTouched?.()\"\n ngpComboboxInput\n />\n\n <button ngpComboboxButton aria-label=\"Toggle dropdown\">\n <ng-icon name=\"heroChevronDown\" />\n </button>\n\n <div *ngpComboboxPortal ngpComboboxDropdown>\n @for (option of filteredOptions(); track option) {\n <div [ngpComboboxOptionValue]=\"option\" ngpComboboxOption>\n {{ option }}\n </div>\n } @empty {\n <div class=\"empty-message\">No options found</div>\n }\n </div>\n </div>\n `,\n styles: `\n [ngpCombobox] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n height: 36px;\n width: 300px;\n border-radius: 8px;\n border: none;\n background-color: var(--ngp-background);\n box-shadow: var(--ngp-input-shadow);\n box-sizing: border-box;\n }\n\n [ngpCombobox][data-focus] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 2px;\n }\n\n [ngpComboboxInput] {\n flex: 1;\n padding: 0 16px;\n border: none;\n background-color: transparent;\n color: var(--ngp-text);\n font-family: inherit;\n font-size: 14px;\n padding: 0 16px;\n outline: none;\n height: 100%;\n }\n\n [ngpComboboxButton] {\n display: inline-flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n width: 36px;\n background-color: transparent;\n border: none;\n color: var(--ngp-text);\n cursor: pointer;\n box-sizing: border-box;\n }\n\n [ngpComboboxDropdown] {\n background-color: var(--ngp-background);\n border: 1px solid var(--ngp-border);\n padding: 0.25rem;\n border-radius: 0.75rem;\n outline: none;\n position: absolute;\n animation: popover-show 0.1s ease-out;\n width: var(--ngp-combobox-width);\n box-shadow: var(--ngp-shadow-lg);\n box-sizing: border-box;\n margin-top: 4px;\n max-height: 240px;\n overflow-y: auto;\n transform-origin: var(--ngp-combobox-transform-origin);\n }\n\n [ngpComboboxDropdown][data-enter] {\n animation: combobox-show 0.1s ease-out;\n }\n\n [ngpComboboxDropdown][data-exit] {\n animation: combobox-hide 0.1s ease-out;\n }\n\n [ngpComboboxOption] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.375rem 0.75rem;\n cursor: pointer;\n border-radius: 0.5rem;\n width: 100%;\n height: 36px;\n font-size: 14px;\n color: var(--ngp-text-primary);\n box-sizing: border-box;\n }\n\n [ngpComboboxOption][data-hover] {\n background-color: var(--ngp-background-hover);\n }\n\n [ngpComboboxOption][data-press] {\n background-color: var(--ngp-background-active);\n }\n\n [ngpComboboxOption][data-active] {\n background-color: var(--ngp-background-active);\n }\n\n .empty-message {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0.5rem;\n color: var(--ngp-text-secondary);\n font-size: 14px;\n font-weight: 500;\n text-align: center;\n }\n\n @keyframes combobox-show {\n 0% {\n opacity: 0;\n transform: translateY(-10px) scale(0.9);\n }\n 100% {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n }\n\n @keyframes combobox-hide {\n 0% {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n 100% {\n opacity: 0;\n transform: translateY(-10px) scale(0.9);\n }\n }\n `,\n})\nexport class Combobox implements ControlValueAccessor {\n /** The options for the combobox. */\n readonly options = input<string[]>([]);\n\n /** The selected value. */\n readonly value = model<string | undefined>();\n\n /** The placeholder for the input. */\n readonly placeholder = input<string>('');\n\n /** The disabled state of the combobox. */\n readonly disabled = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** The filter value. */\n protected readonly filter = signal<string>('');\n\n /** Get the filtered options. */\n protected readonly filteredOptions = computed(() =>\n this.options().filter(option => option.toLowerCase().includes(this.filter().toLowerCase())),\n );\n\n /** Store the form disabled state */\n protected readonly formDisabled = signal(false);\n\n /** The on change callback */\n private onChange?: ChangeFn<string | undefined>;\n\n /** The on touch callback */\n protected onTouched?: TouchedFn;\n\n onFilterChange(event: Event): void {\n const input = event.target as HTMLInputElement;\n this.filter.set(input.value);\n }\n\n writeValue(value: string | undefined): void {\n this.value.set(value);\n this.filter.set(value ?? '');\n }\n\n registerOnChange(fn: ChangeFn<string | undefined>): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.formDisabled.set(isDisabled);\n }\n\n protected onValueChange(value: string): void {\n this.onChange?.(value);\n // update the filter value\n this.filter.set(value);\n }\n\n protected resetOnClose(open: boolean): void {\n // if the dropdown is closed, reset the filter value\n if (open) {\n return;\n }\n\n // if the filter value is empty, clear the value and notify the form control\n if (this.filter() === '') {\n this.value.set(undefined);\n this.onChange?.(undefined);\n } else {\n // otherwise set the filter value to the selected value\n this.filter.set(this.value() ?? '');\n }\n }\n}\n",
|
|
377
377
|
"hasVariants": false,
|
|
378
378
|
"hasSizes": true
|
|
379
379
|
}
|
|
@@ -486,7 +486,7 @@
|
|
|
486
486
|
}
|
|
487
487
|
],
|
|
488
488
|
"reusableComponent": {
|
|
489
|
-
"code": "import { Component, computed } from '@angular/core';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroChevronLeftMini, heroChevronRightMini } from '@ng-icons/heroicons/mini';\nimport {\n injectDatePickerState,\n NgpDatePicker,\n NgpDatePickerCell,\n NgpDatePickerCellRender,\n NgpDatePickerDateButton,\n NgpDatePickerGrid,\n NgpDatePickerLabel,\n NgpDatePickerNextMonth,\n NgpDatePickerPreviousMonth,\n NgpDatePickerRowRender,\n} from 'ng-primitives/date-picker';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-date-picker',\n hostDirectives: [\n {\n directive: NgpDatePicker,\n inputs: [\n 'ngpDatePickerDate: date',\n 'ngpDatePickerMin: min',\n 'ngpDatePickerMax: max',\n 'ngpDatePickerDisabled: disabled',\n ],\n outputs: ['ngpDatePickerDateChange: dateChange'],\n },\n ],\n imports: [\n NgIcon,\n NgpDatePickerLabel,\n NgpDatePickerNextMonth,\n NgpDatePickerPreviousMonth,\n NgpDatePickerGrid,\n NgpDatePickerCell,\n NgpDatePickerRowRender,\n NgpDatePickerCellRender,\n NgpDatePickerDateButton,\n ],\n providers: [\n provideIcons({ heroChevronRightMini, heroChevronLeftMini }),\n provideValueAccessor(DatePicker),\n ],\n template: `\n <div class=\"date-picker-header\">\n <button ngpDatePickerPreviousMonth aria-label=\"previous month\">\n <ng-icon name=\"heroChevronLeftMini\" />\n </button>\n <h2 ngpDatePickerLabel>{{ label() }}</h2>\n <button ngpDatePickerNextMonth aria-label=\"next month\">\n <ng-icon name=\"heroChevronRightMini\" />\n </button>\n </div>\n <table ngpDatePickerGrid>\n <thead>\n <tr>\n <th scope=\"col\" abbr=\"Sunday\">S</th>\n <th scope=\"col\" abbr=\"Monday\">M</th>\n <th scope=\"col\" abbr=\"Tuesday\">T</th>\n <th scope=\"col\" abbr=\"Wednesday\">W</th>\n <th scope=\"col\" abbr=\"Thursday\">T</th>\n <th scope=\"col\" abbr=\"Friday\">F</th>\n <th scope=\"col\" abbr=\"Saturday\">S</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngpDatePickerRowRender>\n <td *ngpDatePickerCellRender=\"let date\" ngpDatePickerCell>\n <button ngpDatePickerDateButton>\n {{ date.getDate() }}\n </button>\n </td>\n </tr>\n </tbody>\n </table>\n `,\n styles: `\n :host {\n display: inline-block;\n background-color: var(--ngp-background);\n border-radius: 12px;\n padding: 16px;\n box-shadow: var(--ngp-shadow);\n border: 1px solid var(--ngp-border);\n }\n\n .date-picker-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 36px;\n margin-bottom: 16px;\n }\n\n th {\n font-size: 14px;\n font-weight: 500;\n width: 40px;\n height: 40px;\n text-align: center;\n color: var(--ngp-text-secondary);\n }\n\n [ngpDatePickerLabel] {\n font-size: 14px;\n font-weight: 500;\n color: var(--ngp-text-primary);\n }\n\n [ngpDatePickerPreviousMonth],\n [ngpDatePickerNextMonth] {\n all: unset;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n font-size: 20px;\n border: 1px solid var(--ngp-border);\n cursor: pointer;\n }\n\n [ngpDatePickerPreviousMonth][data-hover],\n [ngpDatePickerNextMonth][data-hover] {\n background-color: var(--ngp-background-hover);\n }\n\n [ngpDatePickerPreviousMonth][data-focus-visible],\n [ngpDatePickerNextMonth][data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n }\n\n [ngpDatePickerPreviousMonth][data-press],\n [ngpDatePickerNextMonth][data-press] {\n background-color: var(--ngp-background-active);\n }\n\n [ngpDatePickerPreviousMonth][data-disabled],\n [ngpDatePickerNextMonth][data-disabled] {\n cursor: not-allowed;\n color: var(--ngp-text-disabled);\n }\n\n [ngpDatePickerDateButton] {\n all: unset;\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n cursor: pointer;\n }\n\n [ngpDatePickerDateButton][data-today] {\n color: var(--ngp-text-blue);\n }\n\n [ngpDatePickerDateButton][data-hover] {\n background-color: var(--ngp-background-hover);\n }\n\n [ngpDatePickerDateButton][data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 2px;\n }\n\n [ngpDatePickerDateButton][data-press] {\n background-color: var(--ngp-background-active);\n }\n\n [ngpDatePickerDateButton][data-outside-month] {\n color: var(--ngp-text-disabled);\n }\n\n [ngpDatePickerDateButton][data-selected] {\n background-color: var(--ngp-background-inverse);\n color: var(--ngp-text-inverse);\n }\n\n [ngpDatePickerDateButton][data-selected][data-outside-month] {\n background-color: var(--ngp-background-disabled);\n color: var(--ngp-text-disabled);\n }\n\n [ngpDatePickerDateButton][data-disabled] {\n cursor: not-allowed;\n color: var(--ngp-text-disabled);\n }\n `,\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class DatePicker implements ControlValueAccessor {\n /** Access the date picker host directive */\n private readonly state = injectDatePickerState<Date>();\n\n /**\n * Get the current focused date in string format.\n * @returns The focused date in \"February 2024\" format.\n */\n readonly label = computed(\n () =>\n `${this.state().focusedDate().toLocaleString('default', { month: 'long' })} ${this.state().focusedDate().getFullYear()}`,\n );\n\n /**\n * The onChange callback function for the date picker.\n */\n protected onChange?: ChangeFn<Date | undefined>;\n\n /**\n * The onTouched callback function for the date picker.\n */\n protected onTouched?: TouchedFn;\n\n constructor() {\n // Whenever the user interacts with the date picker, call the onChange function with the new value.\n this.state().dateChange.subscribe(date => this.onChange?.(date));\n }\n\n writeValue(date: Date): void {\n this.state().select(date);\n }\n\n registerOnChange(fn: ChangeFn<Date | undefined>): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.state().disabled.set(isDisabled);\n }\n}\n",
|
|
489
|
+
"code": "import { Component, computed } from '@angular/core';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroChevronLeftMini, heroChevronRightMini } from '@ng-icons/heroicons/mini';\nimport {\n injectDatePickerState,\n NgpDatePicker,\n NgpDatePickerCell,\n NgpDatePickerCellRender,\n NgpDatePickerDateButton,\n NgpDatePickerGrid,\n NgpDatePickerLabel,\n NgpDatePickerNextMonth,\n NgpDatePickerPreviousMonth,\n NgpDatePickerRowRender,\n} from 'ng-primitives/date-picker';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-date-picker',\n hostDirectives: [\n {\n directive: NgpDatePicker,\n inputs: [\n 'ngpDatePickerDate: date',\n 'ngpDatePickerMin: min',\n 'ngpDatePickerMax: max',\n 'ngpDatePickerDisabled: disabled',\n ],\n outputs: ['ngpDatePickerDateChange: dateChange'],\n },\n ],\n imports: [\n NgIcon,\n NgpDatePickerLabel,\n NgpDatePickerNextMonth,\n NgpDatePickerPreviousMonth,\n NgpDatePickerGrid,\n NgpDatePickerCell,\n NgpDatePickerRowRender,\n NgpDatePickerCellRender,\n NgpDatePickerDateButton,\n ],\n providers: [\n provideIcons({ heroChevronRightMini, heroChevronLeftMini }),\n provideValueAccessor(DatePicker),\n ],\n template: `\n <div class=\"date-picker-header\">\n <button ngpDatePickerPreviousMonth aria-label=\"previous month\">\n <ng-icon name=\"heroChevronLeftMini\" />\n </button>\n <h2 ngpDatePickerLabel>{{ label() }}</h2>\n <button ngpDatePickerNextMonth aria-label=\"next month\">\n <ng-icon name=\"heroChevronRightMini\" />\n </button>\n </div>\n <table ngpDatePickerGrid>\n <thead>\n <tr>\n <th scope=\"col\" abbr=\"Sunday\">S</th>\n <th scope=\"col\" abbr=\"Monday\">M</th>\n <th scope=\"col\" abbr=\"Tuesday\">T</th>\n <th scope=\"col\" abbr=\"Wednesday\">W</th>\n <th scope=\"col\" abbr=\"Thursday\">T</th>\n <th scope=\"col\" abbr=\"Friday\">F</th>\n <th scope=\"col\" abbr=\"Saturday\">S</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngpDatePickerRowRender>\n <td *ngpDatePickerCellRender=\"let date\" ngpDatePickerCell>\n <button ngpDatePickerDateButton>\n {{ date.getDate() }}\n </button>\n </td>\n </tr>\n </tbody>\n </table>\n `,\n styles: `\n :host {\n display: inline-block;\n background-color: var(--ngp-background);\n border-radius: 12px;\n padding: 16px;\n box-shadow: var(--ngp-shadow);\n border: 1px solid var(--ngp-border);\n }\n\n .date-picker-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 36px;\n margin-bottom: 16px;\n }\n\n th {\n font-size: 14px;\n font-weight: 500;\n width: 40px;\n height: 40px;\n text-align: center;\n color: var(--ngp-text-secondary);\n }\n\n [ngpDatePickerLabel] {\n font-size: 14px;\n font-weight: 500;\n color: var(--ngp-text-primary);\n }\n\n [ngpDatePickerPreviousMonth],\n [ngpDatePickerNextMonth] {\n all: unset;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n font-size: 20px;\n border: 1px solid var(--ngp-border);\n cursor: pointer;\n }\n\n [ngpDatePickerPreviousMonth][data-hover],\n [ngpDatePickerNextMonth][data-hover] {\n background-color: var(--ngp-background-hover);\n }\n\n [ngpDatePickerPreviousMonth][data-focus-visible],\n [ngpDatePickerNextMonth][data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n }\n\n [ngpDatePickerPreviousMonth][data-press],\n [ngpDatePickerNextMonth][data-press] {\n background-color: var(--ngp-background-active);\n }\n\n [ngpDatePickerPreviousMonth][data-disabled],\n [ngpDatePickerNextMonth][data-disabled] {\n cursor: not-allowed;\n color: var(--ngp-text-disabled);\n }\n\n [ngpDatePickerDateButton] {\n all: unset;\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n cursor: pointer;\n }\n\n [ngpDatePickerDateButton][data-today] {\n color: var(--ngp-text-blue);\n }\n\n [ngpDatePickerDateButton][data-hover] {\n background-color: var(--ngp-background-hover);\n }\n\n [ngpDatePickerDateButton][data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 2px;\n }\n\n [ngpDatePickerDateButton][data-press] {\n background-color: var(--ngp-background-active);\n }\n\n [ngpDatePickerDateButton][data-outside-month] {\n color: var(--ngp-text-disabled);\n }\n\n [ngpDatePickerDateButton][data-selected] {\n background-color: var(--ngp-background-inverse);\n color: var(--ngp-text-inverse);\n }\n\n [ngpDatePickerDateButton][data-selected][data-outside-month] {\n background-color: var(--ngp-background-disabled);\n color: var(--ngp-text-disabled);\n }\n\n [ngpDatePickerDateButton][data-disabled] {\n cursor: not-allowed;\n color: var(--ngp-text-disabled);\n }\n `,\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class DatePicker implements ControlValueAccessor {\n /** Access the date picker host directive */\n private readonly state = injectDatePickerState<Date>();\n\n /**\n * Get the current focused date in string format.\n * @returns The focused date in \"February 2024\" format.\n */\n readonly label = computed(\n () =>\n `${this.state().focusedDate().toLocaleString('default', { month: 'long' })} ${this.state().focusedDate().getFullYear()}`,\n );\n\n /**\n * The onChange callback function for the date picker.\n */\n protected onChange?: ChangeFn<Date | undefined>;\n\n /**\n * The onTouched callback function for the date picker.\n */\n protected onTouched?: TouchedFn;\n\n constructor() {\n // Whenever the user interacts with the date picker, call the onChange function with the new value.\n this.state().dateChange.subscribe(date => this.onChange?.(date));\n }\n\n writeValue(date: Date): void {\n // writing a value from the model must not re-emit through onChange\n this.state().select(date, false, { emit: false });\n }\n\n registerOnChange(fn: ChangeFn<Date | undefined>): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.state().disabled.set(isDisabled);\n }\n}\n",
|
|
490
490
|
"hasVariants": false,
|
|
491
491
|
"hasSizes": true
|
|
492
492
|
}
|
|
@@ -508,6 +508,16 @@
|
|
|
508
508
|
"accessibility": [],
|
|
509
509
|
"examples": []
|
|
510
510
|
},
|
|
511
|
+
{
|
|
512
|
+
"name": "date-time-date-fns",
|
|
513
|
+
"entryPoint": "ng-primitives/date-time-date-fns",
|
|
514
|
+
"exports": [],
|
|
515
|
+
"hasSecondaryEntryPoint": true,
|
|
516
|
+
"category": "date-time",
|
|
517
|
+
"description": "date-time-date-fns primitive component",
|
|
518
|
+
"accessibility": [],
|
|
519
|
+
"examples": []
|
|
520
|
+
},
|
|
511
521
|
{
|
|
512
522
|
"name": "date-time-luxon",
|
|
513
523
|
"entryPoint": "ng-primitives/date-time-luxon",
|
|
@@ -1119,7 +1129,7 @@
|
|
|
1119
1129
|
}
|
|
1120
1130
|
],
|
|
1121
1131
|
"reusableComponent": {
|
|
1122
|
-
"code": "import { Component, computed } from '@angular/core';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport {\n heroChevronDoubleLeft,\n heroChevronDoubleRight,\n heroChevronLeft,\n heroChevronRight,\n} from '@ng-icons/heroicons/outline';\nimport {\n injectPaginationState,\n NgpPagination,\n NgpPaginationButton,\n NgpPaginationFirst,\n NgpPaginationLast,\n NgpPaginationNext,\n NgpPaginationPrevious,\n} from 'ng-primitives/pagination';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-pagination',\n hostDirectives: [\n {\n directive: NgpPagination,\n inputs: [\n 'ngpPaginationPage:page',\n 'ngpPaginationPageCount:pageCount',\n 'ngpPaginationDisabled:disabled',\n ],\n outputs: ['ngpPaginationPageChange:pageChange'],\n },\n ],\n imports: [\n NgpPaginationButton,\n NgpPaginationFirst,\n NgpPaginationLast,\n NgpPaginationNext,\n NgpPaginationPrevious,\n NgIcon,\n ],\n providers: [\n provideValueAccessor(NgpPagination),\n provideIcons({\n heroChevronDoubleLeft,\n heroChevronDoubleRight,\n heroChevronLeft,\n heroChevronRight,\n }),\n ],\n template: `\n <ul>\n <li>\n <button ngpPaginationFirst aria-label=\"First Page\">\n <ng-icon name=\"heroChevronDoubleLeft\" />\n </button>\n </li>\n\n <li>\n <button ngpPaginationPrevious aria-label=\"Previous Page\">\n <ng-icon name=\"heroChevronLeft\" />\n </button>\n </li>\n\n @for (page of pages(); track page) {\n <li>\n <button\n [ngpPaginationButtonPage]=\"page\"\n [attr.aria-label]=\"'Page ' + page\"\n ngpPaginationButton\n >\n {{ page }}\n </button>\n </li>\n }\n\n <li>\n <button ngpPaginationNext aria-label=\"Next Page\">\n <ng-icon name=\"heroChevronRight\" />\n </button>\n </li>\n\n <li>\n <button ngpPaginationLast aria-label=\"Last Page\">\n <ng-icon name=\"heroChevronDoubleRight\" />\n </button>\n </li>\n </ul>\n `,\n styles: `\n ul {\n display: flex;\n align-items: center;\n column-gap: 0.5rem;\n list-style: none;\n }\n\n [ngpPaginationFirst],\n [ngpPaginationPrevious],\n [ngpPaginationButton],\n [ngpPaginationNext],\n [ngpPaginationLast] {\n all: unset;\n display: flex;\n justify-content: center;\n align-items: center;\n width: 2rem;\n height: 2rem;\n border-radius: 0.5rem;\n color: var(--ngp-text-primary);\n outline: none;\n font-size: 14px;\n font-weight: 500;\n background-color: var(--ngp-background);\n box-shadow: var(--ngp-button-shadow);\n cursor: pointer;\n transition: background-color 0.2s;\n\n &[data-hover]:not([data-disabled]):not([data-selected]) {\n background-color: var(--ngp-background-hover);\n }\n\n &[data-focus-visible]:not([data-disabled]) {\n outline: 2px solid var(--ngp-focus-ring);\n }\n\n &[data-press]:not([data-disabled]):not([data-selected]) {\n background-color: var(--ngp-background-active);\n }\n\n &[data-disabled] {\n color: rgb(210 210 210);\n background-color: var(--ngp-background-disabled);\n cursor: not-allowed;\n box-shadow: none;\n }\n\n &[data-selected] {\n background-color: var(--ngp-background-inverse);\n color: var(--ngp-text-inverse);\n }\n }\n `,\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class Pagination implements ControlValueAccessor {\n /** Access the pagination state */\n protected readonly state = injectPaginationState();\n\n /** Get the pages as an array we can iterate over */\n protected readonly pages = computed(() =>\n Array.from({ length: this.state().pageCount() }).map((_, i) => i + 1),\n );\n\n /** The onChange callback */\n private onChange?: ChangeFn<number>;\n\n /** The onTouched callback */\n protected onTouched?: TouchedFn;\n\n constructor() {\n this.state().pageChange.subscribe(value => this.onChange?.(value));\n }\n\n /** Write a new value to the control */\n writeValue(value: number): void {\n this.state().
|
|
1132
|
+
"code": "import { Component, computed } from '@angular/core';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport {\n heroChevronDoubleLeft,\n heroChevronDoubleRight,\n heroChevronLeft,\n heroChevronRight,\n} from '@ng-icons/heroicons/outline';\nimport {\n injectPaginationState,\n NgpPagination,\n NgpPaginationButton,\n NgpPaginationFirst,\n NgpPaginationLast,\n NgpPaginationNext,\n NgpPaginationPrevious,\n} from 'ng-primitives/pagination';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-pagination',\n hostDirectives: [\n {\n directive: NgpPagination,\n inputs: [\n 'ngpPaginationPage:page',\n 'ngpPaginationPageCount:pageCount',\n 'ngpPaginationDisabled:disabled',\n ],\n outputs: ['ngpPaginationPageChange:pageChange'],\n },\n ],\n imports: [\n NgpPaginationButton,\n NgpPaginationFirst,\n NgpPaginationLast,\n NgpPaginationNext,\n NgpPaginationPrevious,\n NgIcon,\n ],\n providers: [\n provideValueAccessor(NgpPagination),\n provideIcons({\n heroChevronDoubleLeft,\n heroChevronDoubleRight,\n heroChevronLeft,\n heroChevronRight,\n }),\n ],\n template: `\n <ul>\n <li>\n <button ngpPaginationFirst aria-label=\"First Page\">\n <ng-icon name=\"heroChevronDoubleLeft\" />\n </button>\n </li>\n\n <li>\n <button ngpPaginationPrevious aria-label=\"Previous Page\">\n <ng-icon name=\"heroChevronLeft\" />\n </button>\n </li>\n\n @for (page of pages(); track page) {\n <li>\n <button\n [ngpPaginationButtonPage]=\"page\"\n [attr.aria-label]=\"'Page ' + page\"\n ngpPaginationButton\n >\n {{ page }}\n </button>\n </li>\n }\n\n <li>\n <button ngpPaginationNext aria-label=\"Next Page\">\n <ng-icon name=\"heroChevronRight\" />\n </button>\n </li>\n\n <li>\n <button ngpPaginationLast aria-label=\"Last Page\">\n <ng-icon name=\"heroChevronDoubleRight\" />\n </button>\n </li>\n </ul>\n `,\n styles: `\n ul {\n display: flex;\n align-items: center;\n column-gap: 0.5rem;\n list-style: none;\n }\n\n [ngpPaginationFirst],\n [ngpPaginationPrevious],\n [ngpPaginationButton],\n [ngpPaginationNext],\n [ngpPaginationLast] {\n all: unset;\n display: flex;\n justify-content: center;\n align-items: center;\n width: 2rem;\n height: 2rem;\n border-radius: 0.5rem;\n color: var(--ngp-text-primary);\n outline: none;\n font-size: 14px;\n font-weight: 500;\n background-color: var(--ngp-background);\n box-shadow: var(--ngp-button-shadow);\n cursor: pointer;\n transition: background-color 0.2s;\n\n &[data-hover]:not([data-disabled]):not([data-selected]) {\n background-color: var(--ngp-background-hover);\n }\n\n &[data-focus-visible]:not([data-disabled]) {\n outline: 2px solid var(--ngp-focus-ring);\n }\n\n &[data-press]:not([data-disabled]):not([data-selected]) {\n background-color: var(--ngp-background-active);\n }\n\n &[data-disabled] {\n color: rgb(210 210 210);\n background-color: var(--ngp-background-disabled);\n cursor: not-allowed;\n box-shadow: none;\n }\n\n &[data-selected] {\n background-color: var(--ngp-background-inverse);\n color: var(--ngp-text-inverse);\n }\n }\n `,\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class Pagination implements ControlValueAccessor {\n /** Access the pagination state */\n protected readonly state = injectPaginationState();\n\n /** Get the pages as an array we can iterate over */\n protected readonly pages = computed(() =>\n Array.from({ length: this.state().pageCount() }).map((_, i) => i + 1),\n );\n\n /** The onChange callback */\n private onChange?: ChangeFn<number>;\n\n /** The onTouched callback */\n protected onTouched?: TouchedFn;\n\n constructor() {\n this.state().pageChange.subscribe(value => this.onChange?.(value));\n }\n\n /** Write a new value to the control */\n writeValue(value: number): void {\n // writing a value from the model must not re-emit through onChange\n this.state().setPage(value, { emit: false });\n }\n\n /** Register a callback to be called when the value changes */\n registerOnChange(fn: ChangeFn<number>): void {\n this.onChange = fn;\n }\n\n /** Register a callback to be called when the control is touched */\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n /** Reflect the form control's disabled state onto the pagination. */\n setDisabledState(isDisabled: boolean): void {\n this.state().setDisabled(isDisabled);\n }\n}\n",
|
|
1123
1133
|
"hasVariants": false,
|
|
1124
1134
|
"hasSizes": true
|
|
1125
1135
|
}
|
|
@@ -1580,7 +1590,7 @@
|
|
|
1580
1590
|
}
|
|
1581
1591
|
],
|
|
1582
1592
|
"reusableComponent": {
|
|
1583
|
-
"code": "import { Component, input } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor } from '@angular/forms';\nimport {\n injectSliderState,\n NgpSlider,\n NgpSliderRange,\n NgpSliderThumb,\n NgpSliderTrack,\n} from 'ng-primitives/slider';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-slider',\n hostDirectives: [\n {\n directive: NgpSlider,\n inputs: [\n 'ngpSliderValue:value',\n 'ngpSliderMin:min',\n 'ngpSliderMax:max',\n 'ngpSliderDisabled:disabled',\n ],\n outputs: ['ngpSliderValueChange:valueChange'],\n },\n ],\n imports: [NgpSliderTrack, NgpSliderRange, NgpSliderThumb],\n providers: [provideValueAccessor(Slider)],\n template: `\n <div ngpSliderTrack>\n <div ngpSliderRange></div>\n </div>\n <div [ariaLabel]=\"ariaLabel()\" ngpSliderThumb></div>\n `,\n styles: `\n :host {\n display: flex;\n position: relative;\n width: 200px;\n height: 20px;\n touch-action: none;\n user-select: none;\n align-items: center;\n }\n\n [ngpSliderTrack] {\n position: relative;\n height: 5px;\n width: 100%;\n border-radius: 999px;\n background-color: var(--ngp-background-secondary);\n }\n\n [ngpSliderRange] {\n position: absolute;\n height: 100%;\n border-radius: 999px;\n background-color: var(--ngp-background-inverse);\n }\n\n [ngpSliderThumb] {\n position: absolute;\n display: block;\n height: 20px;\n width: 20px;\n border-radius: 10px;\n background-color: white;\n box-shadow: var(--ngp-button-shadow);\n outline: none;\n transform: translateX(-50%);\n }\n\n [ngpSliderThumb][data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 0;\n }\n `,\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class Slider implements ControlValueAccessor {\n /** Access the slider state */\n private readonly state = injectSliderState();\n\n /** Forward the aria-label to the thumb */\n readonly ariaLabel = input<string | null>(null, {\n alias: 'aria-label',\n });\n\n /**\n * The onChange callback function.\n */\n private onChange?: ChangeFn<number>;\n\n /**\n * The onTouched callback function.\n */\n protected onTouched?: TouchedFn;\n\n constructor() {\n // Whenever the user interacts with the slider, call the onChange function with the new value.\n this.state()\n .valueChange.pipe(takeUntilDestroyed())\n .subscribe(value => this.onChange?.(value));\n }\n\n writeValue(value: number): void {\n this.state().setValue(value);\n }\n\n registerOnChange(fn: ChangeFn<number>): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.state().setDisabled(isDisabled);\n }\n}\n",
|
|
1593
|
+
"code": "import { Component, input } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor } from '@angular/forms';\nimport {\n injectSliderState,\n NgpSlider,\n NgpSliderRange,\n NgpSliderThumb,\n NgpSliderTrack,\n} from 'ng-primitives/slider';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-slider',\n hostDirectives: [\n {\n directive: NgpSlider,\n inputs: [\n 'ngpSliderValue:value',\n 'ngpSliderMin:min',\n 'ngpSliderMax:max',\n 'ngpSliderDisabled:disabled',\n ],\n outputs: ['ngpSliderValueChange:valueChange'],\n },\n ],\n imports: [NgpSliderTrack, NgpSliderRange, NgpSliderThumb],\n providers: [provideValueAccessor(Slider)],\n template: `\n <div ngpSliderTrack>\n <div ngpSliderRange></div>\n </div>\n <div [ariaLabel]=\"ariaLabel()\" ngpSliderThumb></div>\n `,\n styles: `\n :host {\n display: flex;\n position: relative;\n width: 200px;\n height: 20px;\n touch-action: none;\n user-select: none;\n align-items: center;\n }\n\n [ngpSliderTrack] {\n position: relative;\n height: 5px;\n width: 100%;\n border-radius: 999px;\n background-color: var(--ngp-background-secondary);\n }\n\n [ngpSliderRange] {\n position: absolute;\n height: 100%;\n border-radius: 999px;\n background-color: var(--ngp-background-inverse);\n }\n\n [ngpSliderThumb] {\n position: absolute;\n display: block;\n height: 20px;\n width: 20px;\n border-radius: 10px;\n background-color: white;\n box-shadow: var(--ngp-button-shadow);\n outline: none;\n transform: translateX(-50%);\n }\n\n [ngpSliderThumb][data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 0;\n }\n `,\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class Slider implements ControlValueAccessor {\n /** Access the slider state */\n private readonly state = injectSliderState();\n\n /** Forward the aria-label to the thumb */\n readonly ariaLabel = input<string | null>(null, {\n alias: 'aria-label',\n });\n\n /**\n * The onChange callback function.\n */\n private onChange?: ChangeFn<number>;\n\n /**\n * The onTouched callback function.\n */\n protected onTouched?: TouchedFn;\n\n constructor() {\n // Whenever the user interacts with the slider, call the onChange function with the new value.\n this.state()\n .valueChange.pipe(takeUntilDestroyed())\n .subscribe(value => this.onChange?.(value));\n }\n\n writeValue(value: number): void {\n // writing a value from the model must not re-emit through onChange\n this.state().setValue(value, { emit: false });\n }\n\n registerOnChange(fn: ChangeFn<number>): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.state().setDisabled(isDisabled);\n }\n}\n",
|
|
1584
1594
|
"hasVariants": false,
|
|
1585
1595
|
"hasSizes": false
|
|
1586
1596
|
}
|
|
@@ -1626,7 +1636,7 @@
|
|
|
1626
1636
|
}
|
|
1627
1637
|
],
|
|
1628
1638
|
"reusableComponent": {
|
|
1629
|
-
"code": "import { Component } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { injectSwitchState, NgpSwitch, NgpSwitchThumb } from 'ng-primitives/switch';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-switch',\n hostDirectives: [\n {\n directive: NgpSwitch,\n inputs: ['ngpSwitchChecked:checked', 'ngpSwitchDisabled:disabled'],\n outputs: ['ngpSwitchCheckedChange:checkedChange'],\n },\n ],\n imports: [NgpSwitchThumb],\n template: `\n <span ngpSwitchThumb></span>\n `,\n styles: `\n :host {\n display: inline-flex;\n align-items: center;\n position: relative;\n width: 2.5rem;\n height: 1.5rem;\n border-radius: 999px;\n background-color: var(--ngp-background-secondary);\n border: 1px solid var(--ngp-border);\n padding: 0;\n outline: none;\n transition-property:\n color, background-color, border-color, text-decoration-color, fill, stroke;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n box-sizing: border-box;\n }\n\n :host[data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n }\n\n :host[data-checked] {\n background-color: var(--ngp-background-blue);\n border-color: var(--ngp-border-blue);\n }\n\n [ngpSwitchThumb] {\n display: block;\n height: 1.25rem;\n width: 1.25rem;\n border-radius: 999px;\n background-color: white;\n box-shadow: var(--ngp-button-shadow);\n outline: none;\n transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1);\n transform: translateX(1px);\n box-sizing: border-box;\n }\n\n [ngpSwitchThumb][data-checked] {\n transform: translateX(17px);\n }\n `,\n providers: [provideValueAccessor(Switch)],\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class Switch implements ControlValueAccessor {\n /** Access the switch state. */\n private readonly switch = injectSwitchState();\n\n /** The on change callback */\n private onChange?: ChangeFn<boolean>;\n\n /** The on touched callback */\n protected onTouched?: TouchedFn;\n\n constructor() {\n // Any time the switch changes, update the form value.\n this.switch()\n .checkedChange.pipe(takeUntilDestroyed())\n .subscribe(value => this.onChange?.(value));\n }\n\n /** Write a new value to the switch. */\n writeValue(value: boolean): void {\n this.switch().setChecked(value);\n }\n\n /** Register a callback function to be called when the value changes. */\n registerOnChange(fn: ChangeFn<boolean>): void {\n this.onChange = fn;\n }\n\n /** Register a callback function to be called when the switch is touched. */\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n /** Set the disabled state of the switch. */\n setDisabledState(isDisabled: boolean): void {\n this.switch().setDisabled(isDisabled);\n }\n}\n",
|
|
1639
|
+
"code": "import { Component } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { injectSwitchState, NgpSwitch, NgpSwitchThumb } from 'ng-primitives/switch';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-switch',\n hostDirectives: [\n {\n directive: NgpSwitch,\n inputs: ['ngpSwitchChecked:checked', 'ngpSwitchDisabled:disabled'],\n outputs: ['ngpSwitchCheckedChange:checkedChange'],\n },\n ],\n imports: [NgpSwitchThumb],\n template: `\n <span ngpSwitchThumb></span>\n `,\n styles: `\n :host {\n display: inline-flex;\n align-items: center;\n position: relative;\n width: 2.5rem;\n height: 1.5rem;\n border-radius: 999px;\n background-color: var(--ngp-background-secondary);\n border: 1px solid var(--ngp-border);\n padding: 0;\n outline: none;\n transition-property:\n color, background-color, border-color, text-decoration-color, fill, stroke;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n box-sizing: border-box;\n }\n\n :host[data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n }\n\n :host[data-checked] {\n background-color: var(--ngp-background-blue);\n border-color: var(--ngp-border-blue);\n }\n\n [ngpSwitchThumb] {\n display: block;\n height: 1.25rem;\n width: 1.25rem;\n border-radius: 999px;\n background-color: white;\n box-shadow: var(--ngp-button-shadow);\n outline: none;\n transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1);\n transform: translateX(1px);\n box-sizing: border-box;\n }\n\n [ngpSwitchThumb][data-checked] {\n transform: translateX(17px);\n }\n `,\n providers: [provideValueAccessor(Switch)],\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class Switch implements ControlValueAccessor {\n /** Access the switch state. */\n private readonly switch = injectSwitchState();\n\n /** The on change callback */\n private onChange?: ChangeFn<boolean>;\n\n /** The on touched callback */\n protected onTouched?: TouchedFn;\n\n constructor() {\n // Any time the switch changes, update the form value.\n this.switch()\n .checkedChange.pipe(takeUntilDestroyed())\n .subscribe(value => this.onChange?.(value));\n }\n\n /** Write a new value to the switch. */\n writeValue(value: boolean): void {\n // writing a value from the model must not re-emit through onChange\n this.switch().setChecked(value, { emit: false });\n }\n\n /** Register a callback function to be called when the value changes. */\n registerOnChange(fn: ChangeFn<boolean>): void {\n this.onChange = fn;\n }\n\n /** Register a callback function to be called when the switch is touched. */\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n /** Set the disabled state of the switch. */\n setDisabledState(isDisabled: boolean): void {\n this.switch().setDisabled(isDisabled);\n }\n}\n",
|
|
1630
1640
|
"hasVariants": false,
|
|
1631
1641
|
"hasSizes": false
|
|
1632
1642
|
}
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
"name": "checkbox",
|
|
25
|
-
"code": "import { Component } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroCheckMini, heroMinusMini } from '@ng-icons/heroicons/mini';\nimport { injectCheckboxState, NgpCheckbox } from 'ng-primitives/checkbox';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-checkbox',\n hostDirectives: [\n {\n directive: NgpCheckbox,\n inputs: [\n 'ngpCheckboxChecked:checked',\n 'ngpCheckboxIndeterminate:indeterminate',\n 'ngpCheckboxDisabled:disabled',\n ],\n outputs: [\n 'ngpCheckboxCheckedChange:checkedChange',\n 'ngpCheckboxIndeterminateChange:indeterminateChange',\n ],\n },\n ],\n providers: [provideValueAccessor(Checkbox), provideIcons({ heroCheckMini, heroMinusMini })],\n imports: [NgIcon],\n template: `\n @if (state().indeterminate()) {\n <ng-icon name=\"heroMinusMini\" />\n } @else if (state().checked()) {\n <ng-icon name=\"heroCheckMini\" />\n }\n `,\n styles: `\n :host {\n display: flex;\n width: 1.25rem;\n height: 1.25rem;\n cursor: pointer;\n align-items: center;\n justify-content: center;\n border-radius: 0.25rem;\n border: 1px solid var(--ngp-border);\n background-color: transparent;\n padding: 0;\n outline: none;\n flex: none;\n color: var(--ngp-text-inverse);\n font-size: 0.75rem;\n }\n\n :host[data-hover] {\n background-color: var(--ngp-background-hover);\n }\n\n :host[data-checked],\n :host[data-indeterminate] {\n border-color: var(--ngp-background-inverse);\n background-color: var(--ngp-background-inverse);\n }\n\n :host[data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 2px;\n }\n `,\n host: {\n '(focusout)': 'onTouchedFn?.()',\n },\n})\nexport class Checkbox implements ControlValueAccessor {\n /**\n * The checked state of the checkbox.\n */\n protected readonly state = injectCheckboxState();\n\n /**\n * The onChange function for the checkbox.\n */\n protected onChangeFn?: ChangeFn<boolean>;\n\n /**\n * The onTouched function for the checkbox.\n */\n protected onTouchedFn?: TouchedFn;\n\n constructor() {\n // Whenever the user interacts with the checkbox, call the onChange function with the new value.\n this.state()\n .checkedChange.pipe(takeUntilDestroyed())\n .subscribe(checked => this.onChangeFn?.(checked));\n }\n\n writeValue(checked: boolean): void {\n this.state().setChecked(checked);\n }\n\n registerOnChange(fn: ChangeFn<boolean>): void {\n this.onChangeFn = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouchedFn = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.state().setDisabled(isDisabled);\n }\n}\n",
|
|
25
|
+
"code": "import { Component } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroCheckMini, heroMinusMini } from '@ng-icons/heroicons/mini';\nimport { injectCheckboxState, NgpCheckbox } from 'ng-primitives/checkbox';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-checkbox',\n hostDirectives: [\n {\n directive: NgpCheckbox,\n inputs: [\n 'ngpCheckboxChecked:checked',\n 'ngpCheckboxIndeterminate:indeterminate',\n 'ngpCheckboxDisabled:disabled',\n ],\n outputs: [\n 'ngpCheckboxCheckedChange:checkedChange',\n 'ngpCheckboxIndeterminateChange:indeterminateChange',\n ],\n },\n ],\n providers: [provideValueAccessor(Checkbox), provideIcons({ heroCheckMini, heroMinusMini })],\n imports: [NgIcon],\n template: `\n @if (state().indeterminate()) {\n <ng-icon name=\"heroMinusMini\" />\n } @else if (state().checked()) {\n <ng-icon name=\"heroCheckMini\" />\n }\n `,\n styles: `\n :host {\n display: flex;\n width: 1.25rem;\n height: 1.25rem;\n cursor: pointer;\n align-items: center;\n justify-content: center;\n border-radius: 0.25rem;\n border: 1px solid var(--ngp-border);\n background-color: transparent;\n padding: 0;\n outline: none;\n flex: none;\n color: var(--ngp-text-inverse);\n font-size: 0.75rem;\n }\n\n :host[data-hover] {\n background-color: var(--ngp-background-hover);\n }\n\n :host[data-checked],\n :host[data-indeterminate] {\n border-color: var(--ngp-background-inverse);\n background-color: var(--ngp-background-inverse);\n }\n\n :host[data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 2px;\n }\n `,\n host: {\n '(focusout)': 'onTouchedFn?.()',\n },\n})\nexport class Checkbox implements ControlValueAccessor {\n /**\n * The checked state of the checkbox.\n */\n protected readonly state = injectCheckboxState();\n\n /**\n * The onChange function for the checkbox.\n */\n protected onChangeFn?: ChangeFn<boolean>;\n\n /**\n * The onTouched function for the checkbox.\n */\n protected onTouchedFn?: TouchedFn;\n\n constructor() {\n // Whenever the user interacts with the checkbox, call the onChange function with the new value.\n this.state()\n .checkedChange.pipe(takeUntilDestroyed())\n .subscribe(checked => this.onChangeFn?.(checked));\n }\n\n writeValue(checked: boolean): void {\n // writing a value from the model must not re-emit through onChange\n this.state().setChecked(checked, { emit: false });\n }\n\n registerOnChange(fn: ChangeFn<boolean>): void {\n this.onChangeFn = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouchedFn = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.state().setDisabled(isDisabled);\n }\n}\n",
|
|
26
26
|
"primitive": "checkbox",
|
|
27
27
|
"hasVariants": false,
|
|
28
28
|
"hasSizes": true
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"name": "combobox",
|
|
32
|
-
"code": "import { BooleanInput } from '@angular/cdk/coercion';\nimport { booleanAttribute, Component, computed, input, model, signal } from '@angular/core';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroChevronDown } from '@ng-icons/heroicons/outline';\nimport {\n NgpCombobox,\n NgpComboboxButton,\n NgpComboboxDropdown,\n NgpComboboxInput,\n NgpComboboxOption,\n NgpComboboxPortal,\n} from 'ng-primitives/combobox';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-combobox',\n imports: [\n NgpCombobox,\n NgpComboboxDropdown,\n NgpComboboxOption,\n NgpComboboxInput,\n NgpComboboxPortal,\n NgpComboboxButton,\n NgIcon,\n ],\n providers: [provideIcons({ heroChevronDown }), provideValueAccessor(Combobox)],\n template: `\n <div\n [(ngpComboboxValue)]=\"value\"\n [ngpComboboxDisabled]=\"disabled() || formDisabled()\"\n (ngpComboboxOpenChange)=\"resetOnClose($event)\"\n (ngpComboboxValueChange)=\"onValueChange($event)\"\n ngpCombobox\n >\n <input\n [value]=\"filter()\"\n [placeholder]=\"placeholder()\"\n (input)=\"onFilterChange($event)\"\n (blur)=\"onTouched?.()\"\n ngpComboboxInput\n />\n\n <button ngpComboboxButton aria-label=\"Toggle dropdown\">\n <ng-icon name=\"heroChevronDown\" />\n </button>\n\n <div *ngpComboboxPortal ngpComboboxDropdown>\n @for (option of filteredOptions(); track option) {\n <div [ngpComboboxOptionValue]=\"option\" ngpComboboxOption>\n {{ option }}\n </div>\n } @empty {\n <div class=\"empty-message\">No options found</div>\n }\n </div>\n </div>\n `,\n styles: `\n [ngpCombobox] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n height: 36px;\n width: 300px;\n border-radius: 8px;\n border: none;\n background-color: var(--ngp-background);\n box-shadow: var(--ngp-input-shadow);\n box-sizing: border-box;\n }\n\n [ngpCombobox][data-focus] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 2px;\n }\n\n [ngpComboboxInput] {\n flex: 1;\n padding: 0 16px;\n border: none;\n background-color: transparent;\n color: var(--ngp-text);\n font-family: inherit;\n font-size: 14px;\n padding: 0 16px;\n outline: none;\n height: 100%;\n }\n\n [ngpComboboxButton] {\n display: inline-flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n width: 36px;\n background-color: transparent;\n border: none;\n color: var(--ngp-text);\n cursor: pointer;\n box-sizing: border-box;\n }\n\n [ngpComboboxDropdown] {\n background-color: var(--ngp-background);\n border: 1px solid var(--ngp-border);\n padding: 0.25rem;\n border-radius: 0.75rem;\n outline: none;\n position: absolute;\n animation: popover-show 0.1s ease-out;\n width: var(--ngp-combobox-width);\n box-shadow: var(--ngp-shadow-lg);\n box-sizing: border-box;\n margin-top: 4px;\n max-height: 240px;\n overflow-y: auto;\n transform-origin: var(--ngp-combobox-transform-origin);\n }\n\n [ngpComboboxDropdown][data-enter] {\n animation: combobox-show 0.1s ease-out;\n }\n\n [ngpComboboxDropdown][data-exit] {\n animation: combobox-hide 0.1s ease-out;\n }\n\n [ngpComboboxOption] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.375rem 0.75rem;\n cursor: pointer;\n border-radius: 0.5rem;\n width: 100%;\n height: 36px;\n font-size: 14px;\n color: var(--ngp-text-primary);\n box-sizing: border-box;\n }\n\n [ngpComboboxOption][data-hover] {\n background-color: var(--ngp-background-hover);\n }\n\n [ngpComboboxOption][data-press] {\n background-color: var(--ngp-background-active);\n }\n\n [ngpComboboxOption][data-active] {\n background-color: var(--ngp-background-active);\n }\n\n .empty-message {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0.5rem;\n color: var(--ngp-text-secondary);\n font-size: 14px;\n font-weight: 500;\n text-align: center;\n }\n\n @keyframes combobox-show {\n 0% {\n opacity: 0;\n transform: translateY(-10px) scale(0.9);\n }\n 100% {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n }\n\n @keyframes combobox-hide {\n 0% {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n 100% {\n opacity: 0;\n transform: translateY(-10px) scale(0.9);\n }\n }\n `,\n})\nexport class Combobox implements ControlValueAccessor {\n /** The options for the combobox. */\n readonly options = input<string[]>([]);\n\n /** The selected value. */\n readonly value = model<string | undefined>();\n\n /** The placeholder for the input. */\n readonly placeholder = input<string>('');\n\n /** The disabled state of the combobox. */\n readonly disabled = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** The filter value. */\n protected readonly filter = signal<string>('');\n\n /** Get the filtered options. */\n protected readonly filteredOptions = computed(() =>\n this.options().filter(option => option.toLowerCase().includes(this.filter().toLowerCase())),\n );\n\n /** Store the form disabled state */\n protected readonly formDisabled = signal(false);\n\n /** The on change callback */\n private onChange?: ChangeFn<string>;\n\n /** The on touch callback */\n protected onTouched?: TouchedFn;\n\n onFilterChange(event: Event): void {\n const input = event.target as HTMLInputElement;\n this.filter.set(input.value);\n }\n\n writeValue(value: string | undefined): void {\n this.value.set(value);\n this.filter.set(value ?? '');\n }\n\n registerOnChange(fn: ChangeFn<string | undefined>): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.formDisabled.set(isDisabled);\n }\n\n protected onValueChange(value: string): void {\n this.onChange?.(value);\n // update the filter value\n this.filter.set(value);\n }\n\n protected resetOnClose(open: boolean): void {\n // if the dropdown is closed, reset the filter value\n if (open) {\n return;\n }\n\n // if the filter value is empty,
|
|
32
|
+
"code": "import { BooleanInput } from '@angular/cdk/coercion';\nimport { booleanAttribute, Component, computed, input, model, signal } from '@angular/core';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroChevronDown } from '@ng-icons/heroicons/outline';\nimport {\n NgpCombobox,\n NgpComboboxButton,\n NgpComboboxDropdown,\n NgpComboboxInput,\n NgpComboboxOption,\n NgpComboboxPortal,\n} from 'ng-primitives/combobox';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-combobox',\n imports: [\n NgpCombobox,\n NgpComboboxDropdown,\n NgpComboboxOption,\n NgpComboboxInput,\n NgpComboboxPortal,\n NgpComboboxButton,\n NgIcon,\n ],\n providers: [provideIcons({ heroChevronDown }), provideValueAccessor(Combobox)],\n template: `\n <div\n [(ngpComboboxValue)]=\"value\"\n [ngpComboboxDisabled]=\"disabled() || formDisabled()\"\n (ngpComboboxOpenChange)=\"resetOnClose($event)\"\n (ngpComboboxValueChange)=\"onValueChange($event)\"\n ngpCombobox\n >\n <input\n [value]=\"filter()\"\n [placeholder]=\"placeholder()\"\n (input)=\"onFilterChange($event)\"\n (blur)=\"onTouched?.()\"\n ngpComboboxInput\n />\n\n <button ngpComboboxButton aria-label=\"Toggle dropdown\">\n <ng-icon name=\"heroChevronDown\" />\n </button>\n\n <div *ngpComboboxPortal ngpComboboxDropdown>\n @for (option of filteredOptions(); track option) {\n <div [ngpComboboxOptionValue]=\"option\" ngpComboboxOption>\n {{ option }}\n </div>\n } @empty {\n <div class=\"empty-message\">No options found</div>\n }\n </div>\n </div>\n `,\n styles: `\n [ngpCombobox] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n height: 36px;\n width: 300px;\n border-radius: 8px;\n border: none;\n background-color: var(--ngp-background);\n box-shadow: var(--ngp-input-shadow);\n box-sizing: border-box;\n }\n\n [ngpCombobox][data-focus] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 2px;\n }\n\n [ngpComboboxInput] {\n flex: 1;\n padding: 0 16px;\n border: none;\n background-color: transparent;\n color: var(--ngp-text);\n font-family: inherit;\n font-size: 14px;\n padding: 0 16px;\n outline: none;\n height: 100%;\n }\n\n [ngpComboboxButton] {\n display: inline-flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n width: 36px;\n background-color: transparent;\n border: none;\n color: var(--ngp-text);\n cursor: pointer;\n box-sizing: border-box;\n }\n\n [ngpComboboxDropdown] {\n background-color: var(--ngp-background);\n border: 1px solid var(--ngp-border);\n padding: 0.25rem;\n border-radius: 0.75rem;\n outline: none;\n position: absolute;\n animation: popover-show 0.1s ease-out;\n width: var(--ngp-combobox-width);\n box-shadow: var(--ngp-shadow-lg);\n box-sizing: border-box;\n margin-top: 4px;\n max-height: 240px;\n overflow-y: auto;\n transform-origin: var(--ngp-combobox-transform-origin);\n }\n\n [ngpComboboxDropdown][data-enter] {\n animation: combobox-show 0.1s ease-out;\n }\n\n [ngpComboboxDropdown][data-exit] {\n animation: combobox-hide 0.1s ease-out;\n }\n\n [ngpComboboxOption] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.375rem 0.75rem;\n cursor: pointer;\n border-radius: 0.5rem;\n width: 100%;\n height: 36px;\n font-size: 14px;\n color: var(--ngp-text-primary);\n box-sizing: border-box;\n }\n\n [ngpComboboxOption][data-hover] {\n background-color: var(--ngp-background-hover);\n }\n\n [ngpComboboxOption][data-press] {\n background-color: var(--ngp-background-active);\n }\n\n [ngpComboboxOption][data-active] {\n background-color: var(--ngp-background-active);\n }\n\n .empty-message {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0.5rem;\n color: var(--ngp-text-secondary);\n font-size: 14px;\n font-weight: 500;\n text-align: center;\n }\n\n @keyframes combobox-show {\n 0% {\n opacity: 0;\n transform: translateY(-10px) scale(0.9);\n }\n 100% {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n }\n\n @keyframes combobox-hide {\n 0% {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n 100% {\n opacity: 0;\n transform: translateY(-10px) scale(0.9);\n }\n }\n `,\n})\nexport class Combobox implements ControlValueAccessor {\n /** The options for the combobox. */\n readonly options = input<string[]>([]);\n\n /** The selected value. */\n readonly value = model<string | undefined>();\n\n /** The placeholder for the input. */\n readonly placeholder = input<string>('');\n\n /** The disabled state of the combobox. */\n readonly disabled = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** The filter value. */\n protected readonly filter = signal<string>('');\n\n /** Get the filtered options. */\n protected readonly filteredOptions = computed(() =>\n this.options().filter(option => option.toLowerCase().includes(this.filter().toLowerCase())),\n );\n\n /** Store the form disabled state */\n protected readonly formDisabled = signal(false);\n\n /** The on change callback */\n private onChange?: ChangeFn<string | undefined>;\n\n /** The on touch callback */\n protected onTouched?: TouchedFn;\n\n onFilterChange(event: Event): void {\n const input = event.target as HTMLInputElement;\n this.filter.set(input.value);\n }\n\n writeValue(value: string | undefined): void {\n this.value.set(value);\n this.filter.set(value ?? '');\n }\n\n registerOnChange(fn: ChangeFn<string | undefined>): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.formDisabled.set(isDisabled);\n }\n\n protected onValueChange(value: string): void {\n this.onChange?.(value);\n // update the filter value\n this.filter.set(value);\n }\n\n protected resetOnClose(open: boolean): void {\n // if the dropdown is closed, reset the filter value\n if (open) {\n return;\n }\n\n // if the filter value is empty, clear the value and notify the form control\n if (this.filter() === '') {\n this.value.set(undefined);\n this.onChange?.(undefined);\n } else {\n // otherwise set the filter value to the selected value\n this.filter.set(this.value() ?? '');\n }\n }\n}\n",
|
|
33
33
|
"primitive": "combobox",
|
|
34
34
|
"hasVariants": false,
|
|
35
35
|
"hasSizes": true
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
"name": "date-picker",
|
|
46
|
-
"code": "import { Component, computed } from '@angular/core';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroChevronLeftMini, heroChevronRightMini } from '@ng-icons/heroicons/mini';\nimport {\n injectDatePickerState,\n NgpDatePicker,\n NgpDatePickerCell,\n NgpDatePickerCellRender,\n NgpDatePickerDateButton,\n NgpDatePickerGrid,\n NgpDatePickerLabel,\n NgpDatePickerNextMonth,\n NgpDatePickerPreviousMonth,\n NgpDatePickerRowRender,\n} from 'ng-primitives/date-picker';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-date-picker',\n hostDirectives: [\n {\n directive: NgpDatePicker,\n inputs: [\n 'ngpDatePickerDate: date',\n 'ngpDatePickerMin: min',\n 'ngpDatePickerMax: max',\n 'ngpDatePickerDisabled: disabled',\n ],\n outputs: ['ngpDatePickerDateChange: dateChange'],\n },\n ],\n imports: [\n NgIcon,\n NgpDatePickerLabel,\n NgpDatePickerNextMonth,\n NgpDatePickerPreviousMonth,\n NgpDatePickerGrid,\n NgpDatePickerCell,\n NgpDatePickerRowRender,\n NgpDatePickerCellRender,\n NgpDatePickerDateButton,\n ],\n providers: [\n provideIcons({ heroChevronRightMini, heroChevronLeftMini }),\n provideValueAccessor(DatePicker),\n ],\n template: `\n <div class=\"date-picker-header\">\n <button ngpDatePickerPreviousMonth aria-label=\"previous month\">\n <ng-icon name=\"heroChevronLeftMini\" />\n </button>\n <h2 ngpDatePickerLabel>{{ label() }}</h2>\n <button ngpDatePickerNextMonth aria-label=\"next month\">\n <ng-icon name=\"heroChevronRightMini\" />\n </button>\n </div>\n <table ngpDatePickerGrid>\n <thead>\n <tr>\n <th scope=\"col\" abbr=\"Sunday\">S</th>\n <th scope=\"col\" abbr=\"Monday\">M</th>\n <th scope=\"col\" abbr=\"Tuesday\">T</th>\n <th scope=\"col\" abbr=\"Wednesday\">W</th>\n <th scope=\"col\" abbr=\"Thursday\">T</th>\n <th scope=\"col\" abbr=\"Friday\">F</th>\n <th scope=\"col\" abbr=\"Saturday\">S</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngpDatePickerRowRender>\n <td *ngpDatePickerCellRender=\"let date\" ngpDatePickerCell>\n <button ngpDatePickerDateButton>\n {{ date.getDate() }}\n </button>\n </td>\n </tr>\n </tbody>\n </table>\n `,\n styles: `\n :host {\n display: inline-block;\n background-color: var(--ngp-background);\n border-radius: 12px;\n padding: 16px;\n box-shadow: var(--ngp-shadow);\n border: 1px solid var(--ngp-border);\n }\n\n .date-picker-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 36px;\n margin-bottom: 16px;\n }\n\n th {\n font-size: 14px;\n font-weight: 500;\n width: 40px;\n height: 40px;\n text-align: center;\n color: var(--ngp-text-secondary);\n }\n\n [ngpDatePickerLabel] {\n font-size: 14px;\n font-weight: 500;\n color: var(--ngp-text-primary);\n }\n\n [ngpDatePickerPreviousMonth],\n [ngpDatePickerNextMonth] {\n all: unset;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n font-size: 20px;\n border: 1px solid var(--ngp-border);\n cursor: pointer;\n }\n\n [ngpDatePickerPreviousMonth][data-hover],\n [ngpDatePickerNextMonth][data-hover] {\n background-color: var(--ngp-background-hover);\n }\n\n [ngpDatePickerPreviousMonth][data-focus-visible],\n [ngpDatePickerNextMonth][data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n }\n\n [ngpDatePickerPreviousMonth][data-press],\n [ngpDatePickerNextMonth][data-press] {\n background-color: var(--ngp-background-active);\n }\n\n [ngpDatePickerPreviousMonth][data-disabled],\n [ngpDatePickerNextMonth][data-disabled] {\n cursor: not-allowed;\n color: var(--ngp-text-disabled);\n }\n\n [ngpDatePickerDateButton] {\n all: unset;\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n cursor: pointer;\n }\n\n [ngpDatePickerDateButton][data-today] {\n color: var(--ngp-text-blue);\n }\n\n [ngpDatePickerDateButton][data-hover] {\n background-color: var(--ngp-background-hover);\n }\n\n [ngpDatePickerDateButton][data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 2px;\n }\n\n [ngpDatePickerDateButton][data-press] {\n background-color: var(--ngp-background-active);\n }\n\n [ngpDatePickerDateButton][data-outside-month] {\n color: var(--ngp-text-disabled);\n }\n\n [ngpDatePickerDateButton][data-selected] {\n background-color: var(--ngp-background-inverse);\n color: var(--ngp-text-inverse);\n }\n\n [ngpDatePickerDateButton][data-selected][data-outside-month] {\n background-color: var(--ngp-background-disabled);\n color: var(--ngp-text-disabled);\n }\n\n [ngpDatePickerDateButton][data-disabled] {\n cursor: not-allowed;\n color: var(--ngp-text-disabled);\n }\n `,\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class DatePicker implements ControlValueAccessor {\n /** Access the date picker host directive */\n private readonly state = injectDatePickerState<Date>();\n\n /**\n * Get the current focused date in string format.\n * @returns The focused date in \"February 2024\" format.\n */\n readonly label = computed(\n () =>\n `${this.state().focusedDate().toLocaleString('default', { month: 'long' })} ${this.state().focusedDate().getFullYear()}`,\n );\n\n /**\n * The onChange callback function for the date picker.\n */\n protected onChange?: ChangeFn<Date | undefined>;\n\n /**\n * The onTouched callback function for the date picker.\n */\n protected onTouched?: TouchedFn;\n\n constructor() {\n // Whenever the user interacts with the date picker, call the onChange function with the new value.\n this.state().dateChange.subscribe(date => this.onChange?.(date));\n }\n\n writeValue(date: Date): void {\n this.state().select(date);\n }\n\n registerOnChange(fn: ChangeFn<Date | undefined>): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.state().disabled.set(isDisabled);\n }\n}\n",
|
|
46
|
+
"code": "import { Component, computed } from '@angular/core';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroChevronLeftMini, heroChevronRightMini } from '@ng-icons/heroicons/mini';\nimport {\n injectDatePickerState,\n NgpDatePicker,\n NgpDatePickerCell,\n NgpDatePickerCellRender,\n NgpDatePickerDateButton,\n NgpDatePickerGrid,\n NgpDatePickerLabel,\n NgpDatePickerNextMonth,\n NgpDatePickerPreviousMonth,\n NgpDatePickerRowRender,\n} from 'ng-primitives/date-picker';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-date-picker',\n hostDirectives: [\n {\n directive: NgpDatePicker,\n inputs: [\n 'ngpDatePickerDate: date',\n 'ngpDatePickerMin: min',\n 'ngpDatePickerMax: max',\n 'ngpDatePickerDisabled: disabled',\n ],\n outputs: ['ngpDatePickerDateChange: dateChange'],\n },\n ],\n imports: [\n NgIcon,\n NgpDatePickerLabel,\n NgpDatePickerNextMonth,\n NgpDatePickerPreviousMonth,\n NgpDatePickerGrid,\n NgpDatePickerCell,\n NgpDatePickerRowRender,\n NgpDatePickerCellRender,\n NgpDatePickerDateButton,\n ],\n providers: [\n provideIcons({ heroChevronRightMini, heroChevronLeftMini }),\n provideValueAccessor(DatePicker),\n ],\n template: `\n <div class=\"date-picker-header\">\n <button ngpDatePickerPreviousMonth aria-label=\"previous month\">\n <ng-icon name=\"heroChevronLeftMini\" />\n </button>\n <h2 ngpDatePickerLabel>{{ label() }}</h2>\n <button ngpDatePickerNextMonth aria-label=\"next month\">\n <ng-icon name=\"heroChevronRightMini\" />\n </button>\n </div>\n <table ngpDatePickerGrid>\n <thead>\n <tr>\n <th scope=\"col\" abbr=\"Sunday\">S</th>\n <th scope=\"col\" abbr=\"Monday\">M</th>\n <th scope=\"col\" abbr=\"Tuesday\">T</th>\n <th scope=\"col\" abbr=\"Wednesday\">W</th>\n <th scope=\"col\" abbr=\"Thursday\">T</th>\n <th scope=\"col\" abbr=\"Friday\">F</th>\n <th scope=\"col\" abbr=\"Saturday\">S</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngpDatePickerRowRender>\n <td *ngpDatePickerCellRender=\"let date\" ngpDatePickerCell>\n <button ngpDatePickerDateButton>\n {{ date.getDate() }}\n </button>\n </td>\n </tr>\n </tbody>\n </table>\n `,\n styles: `\n :host {\n display: inline-block;\n background-color: var(--ngp-background);\n border-radius: 12px;\n padding: 16px;\n box-shadow: var(--ngp-shadow);\n border: 1px solid var(--ngp-border);\n }\n\n .date-picker-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 36px;\n margin-bottom: 16px;\n }\n\n th {\n font-size: 14px;\n font-weight: 500;\n width: 40px;\n height: 40px;\n text-align: center;\n color: var(--ngp-text-secondary);\n }\n\n [ngpDatePickerLabel] {\n font-size: 14px;\n font-weight: 500;\n color: var(--ngp-text-primary);\n }\n\n [ngpDatePickerPreviousMonth],\n [ngpDatePickerNextMonth] {\n all: unset;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n font-size: 20px;\n border: 1px solid var(--ngp-border);\n cursor: pointer;\n }\n\n [ngpDatePickerPreviousMonth][data-hover],\n [ngpDatePickerNextMonth][data-hover] {\n background-color: var(--ngp-background-hover);\n }\n\n [ngpDatePickerPreviousMonth][data-focus-visible],\n [ngpDatePickerNextMonth][data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n }\n\n [ngpDatePickerPreviousMonth][data-press],\n [ngpDatePickerNextMonth][data-press] {\n background-color: var(--ngp-background-active);\n }\n\n [ngpDatePickerPreviousMonth][data-disabled],\n [ngpDatePickerNextMonth][data-disabled] {\n cursor: not-allowed;\n color: var(--ngp-text-disabled);\n }\n\n [ngpDatePickerDateButton] {\n all: unset;\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n cursor: pointer;\n }\n\n [ngpDatePickerDateButton][data-today] {\n color: var(--ngp-text-blue);\n }\n\n [ngpDatePickerDateButton][data-hover] {\n background-color: var(--ngp-background-hover);\n }\n\n [ngpDatePickerDateButton][data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 2px;\n }\n\n [ngpDatePickerDateButton][data-press] {\n background-color: var(--ngp-background-active);\n }\n\n [ngpDatePickerDateButton][data-outside-month] {\n color: var(--ngp-text-disabled);\n }\n\n [ngpDatePickerDateButton][data-selected] {\n background-color: var(--ngp-background-inverse);\n color: var(--ngp-text-inverse);\n }\n\n [ngpDatePickerDateButton][data-selected][data-outside-month] {\n background-color: var(--ngp-background-disabled);\n color: var(--ngp-text-disabled);\n }\n\n [ngpDatePickerDateButton][data-disabled] {\n cursor: not-allowed;\n color: var(--ngp-text-disabled);\n }\n `,\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class DatePicker implements ControlValueAccessor {\n /** Access the date picker host directive */\n private readonly state = injectDatePickerState<Date>();\n\n /**\n * Get the current focused date in string format.\n * @returns The focused date in \"February 2024\" format.\n */\n readonly label = computed(\n () =>\n `${this.state().focusedDate().toLocaleString('default', { month: 'long' })} ${this.state().focusedDate().getFullYear()}`,\n );\n\n /**\n * The onChange callback function for the date picker.\n */\n protected onChange?: ChangeFn<Date | undefined>;\n\n /**\n * The onTouched callback function for the date picker.\n */\n protected onTouched?: TouchedFn;\n\n constructor() {\n // Whenever the user interacts with the date picker, call the onChange function with the new value.\n this.state().dateChange.subscribe(date => this.onChange?.(date));\n }\n\n writeValue(date: Date): void {\n // writing a value from the model must not re-emit through onChange\n this.state().select(date, false, { emit: false });\n }\n\n registerOnChange(fn: ChangeFn<Date | undefined>): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.state().disabled.set(isDisabled);\n }\n}\n",
|
|
47
47
|
"primitive": "date-picker",
|
|
48
48
|
"hasVariants": false,
|
|
49
49
|
"hasSizes": true
|
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
},
|
|
121
121
|
{
|
|
122
122
|
"name": "pagination",
|
|
123
|
-
"code": "import { Component, computed } from '@angular/core';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport {\n heroChevronDoubleLeft,\n heroChevronDoubleRight,\n heroChevronLeft,\n heroChevronRight,\n} from '@ng-icons/heroicons/outline';\nimport {\n injectPaginationState,\n NgpPagination,\n NgpPaginationButton,\n NgpPaginationFirst,\n NgpPaginationLast,\n NgpPaginationNext,\n NgpPaginationPrevious,\n} from 'ng-primitives/pagination';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-pagination',\n hostDirectives: [\n {\n directive: NgpPagination,\n inputs: [\n 'ngpPaginationPage:page',\n 'ngpPaginationPageCount:pageCount',\n 'ngpPaginationDisabled:disabled',\n ],\n outputs: ['ngpPaginationPageChange:pageChange'],\n },\n ],\n imports: [\n NgpPaginationButton,\n NgpPaginationFirst,\n NgpPaginationLast,\n NgpPaginationNext,\n NgpPaginationPrevious,\n NgIcon,\n ],\n providers: [\n provideValueAccessor(NgpPagination),\n provideIcons({\n heroChevronDoubleLeft,\n heroChevronDoubleRight,\n heroChevronLeft,\n heroChevronRight,\n }),\n ],\n template: `\n <ul>\n <li>\n <button ngpPaginationFirst aria-label=\"First Page\">\n <ng-icon name=\"heroChevronDoubleLeft\" />\n </button>\n </li>\n\n <li>\n <button ngpPaginationPrevious aria-label=\"Previous Page\">\n <ng-icon name=\"heroChevronLeft\" />\n </button>\n </li>\n\n @for (page of pages(); track page) {\n <li>\n <button\n [ngpPaginationButtonPage]=\"page\"\n [attr.aria-label]=\"'Page ' + page\"\n ngpPaginationButton\n >\n {{ page }}\n </button>\n </li>\n }\n\n <li>\n <button ngpPaginationNext aria-label=\"Next Page\">\n <ng-icon name=\"heroChevronRight\" />\n </button>\n </li>\n\n <li>\n <button ngpPaginationLast aria-label=\"Last Page\">\n <ng-icon name=\"heroChevronDoubleRight\" />\n </button>\n </li>\n </ul>\n `,\n styles: `\n ul {\n display: flex;\n align-items: center;\n column-gap: 0.5rem;\n list-style: none;\n }\n\n [ngpPaginationFirst],\n [ngpPaginationPrevious],\n [ngpPaginationButton],\n [ngpPaginationNext],\n [ngpPaginationLast] {\n all: unset;\n display: flex;\n justify-content: center;\n align-items: center;\n width: 2rem;\n height: 2rem;\n border-radius: 0.5rem;\n color: var(--ngp-text-primary);\n outline: none;\n font-size: 14px;\n font-weight: 500;\n background-color: var(--ngp-background);\n box-shadow: var(--ngp-button-shadow);\n cursor: pointer;\n transition: background-color 0.2s;\n\n &[data-hover]:not([data-disabled]):not([data-selected]) {\n background-color: var(--ngp-background-hover);\n }\n\n &[data-focus-visible]:not([data-disabled]) {\n outline: 2px solid var(--ngp-focus-ring);\n }\n\n &[data-press]:not([data-disabled]):not([data-selected]) {\n background-color: var(--ngp-background-active);\n }\n\n &[data-disabled] {\n color: rgb(210 210 210);\n background-color: var(--ngp-background-disabled);\n cursor: not-allowed;\n box-shadow: none;\n }\n\n &[data-selected] {\n background-color: var(--ngp-background-inverse);\n color: var(--ngp-text-inverse);\n }\n }\n `,\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class Pagination implements ControlValueAccessor {\n /** Access the pagination state */\n protected readonly state = injectPaginationState();\n\n /** Get the pages as an array we can iterate over */\n protected readonly pages = computed(() =>\n Array.from({ length: this.state().pageCount() }).map((_, i) => i + 1),\n );\n\n /** The onChange callback */\n private onChange?: ChangeFn<number>;\n\n /** The onTouched callback */\n protected onTouched?: TouchedFn;\n\n constructor() {\n this.state().pageChange.subscribe(value => this.onChange?.(value));\n }\n\n /** Write a new value to the control */\n writeValue(value: number): void {\n this.state().
|
|
123
|
+
"code": "import { Component, computed } from '@angular/core';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport {\n heroChevronDoubleLeft,\n heroChevronDoubleRight,\n heroChevronLeft,\n heroChevronRight,\n} from '@ng-icons/heroicons/outline';\nimport {\n injectPaginationState,\n NgpPagination,\n NgpPaginationButton,\n NgpPaginationFirst,\n NgpPaginationLast,\n NgpPaginationNext,\n NgpPaginationPrevious,\n} from 'ng-primitives/pagination';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-pagination',\n hostDirectives: [\n {\n directive: NgpPagination,\n inputs: [\n 'ngpPaginationPage:page',\n 'ngpPaginationPageCount:pageCount',\n 'ngpPaginationDisabled:disabled',\n ],\n outputs: ['ngpPaginationPageChange:pageChange'],\n },\n ],\n imports: [\n NgpPaginationButton,\n NgpPaginationFirst,\n NgpPaginationLast,\n NgpPaginationNext,\n NgpPaginationPrevious,\n NgIcon,\n ],\n providers: [\n provideValueAccessor(NgpPagination),\n provideIcons({\n heroChevronDoubleLeft,\n heroChevronDoubleRight,\n heroChevronLeft,\n heroChevronRight,\n }),\n ],\n template: `\n <ul>\n <li>\n <button ngpPaginationFirst aria-label=\"First Page\">\n <ng-icon name=\"heroChevronDoubleLeft\" />\n </button>\n </li>\n\n <li>\n <button ngpPaginationPrevious aria-label=\"Previous Page\">\n <ng-icon name=\"heroChevronLeft\" />\n </button>\n </li>\n\n @for (page of pages(); track page) {\n <li>\n <button\n [ngpPaginationButtonPage]=\"page\"\n [attr.aria-label]=\"'Page ' + page\"\n ngpPaginationButton\n >\n {{ page }}\n </button>\n </li>\n }\n\n <li>\n <button ngpPaginationNext aria-label=\"Next Page\">\n <ng-icon name=\"heroChevronRight\" />\n </button>\n </li>\n\n <li>\n <button ngpPaginationLast aria-label=\"Last Page\">\n <ng-icon name=\"heroChevronDoubleRight\" />\n </button>\n </li>\n </ul>\n `,\n styles: `\n ul {\n display: flex;\n align-items: center;\n column-gap: 0.5rem;\n list-style: none;\n }\n\n [ngpPaginationFirst],\n [ngpPaginationPrevious],\n [ngpPaginationButton],\n [ngpPaginationNext],\n [ngpPaginationLast] {\n all: unset;\n display: flex;\n justify-content: center;\n align-items: center;\n width: 2rem;\n height: 2rem;\n border-radius: 0.5rem;\n color: var(--ngp-text-primary);\n outline: none;\n font-size: 14px;\n font-weight: 500;\n background-color: var(--ngp-background);\n box-shadow: var(--ngp-button-shadow);\n cursor: pointer;\n transition: background-color 0.2s;\n\n &[data-hover]:not([data-disabled]):not([data-selected]) {\n background-color: var(--ngp-background-hover);\n }\n\n &[data-focus-visible]:not([data-disabled]) {\n outline: 2px solid var(--ngp-focus-ring);\n }\n\n &[data-press]:not([data-disabled]):not([data-selected]) {\n background-color: var(--ngp-background-active);\n }\n\n &[data-disabled] {\n color: rgb(210 210 210);\n background-color: var(--ngp-background-disabled);\n cursor: not-allowed;\n box-shadow: none;\n }\n\n &[data-selected] {\n background-color: var(--ngp-background-inverse);\n color: var(--ngp-text-inverse);\n }\n }\n `,\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class Pagination implements ControlValueAccessor {\n /** Access the pagination state */\n protected readonly state = injectPaginationState();\n\n /** Get the pages as an array we can iterate over */\n protected readonly pages = computed(() =>\n Array.from({ length: this.state().pageCount() }).map((_, i) => i + 1),\n );\n\n /** The onChange callback */\n private onChange?: ChangeFn<number>;\n\n /** The onTouched callback */\n protected onTouched?: TouchedFn;\n\n constructor() {\n this.state().pageChange.subscribe(value => this.onChange?.(value));\n }\n\n /** Write a new value to the control */\n writeValue(value: number): void {\n // writing a value from the model must not re-emit through onChange\n this.state().setPage(value, { emit: false });\n }\n\n /** Register a callback to be called when the value changes */\n registerOnChange(fn: ChangeFn<number>): void {\n this.onChange = fn;\n }\n\n /** Register a callback to be called when the control is touched */\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n /** Reflect the form control's disabled state onto the pagination. */\n setDisabledState(isDisabled: boolean): void {\n this.state().setDisabled(isDisabled);\n }\n}\n",
|
|
124
124
|
"primitive": "pagination",
|
|
125
125
|
"hasVariants": false,
|
|
126
126
|
"hasSizes": true
|
|
@@ -148,7 +148,7 @@
|
|
|
148
148
|
},
|
|
149
149
|
{
|
|
150
150
|
"name": "range-slider",
|
|
151
|
-
"code": "import { Component, input } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor } from '@angular/forms';\nimport {\n injectRangeSliderState,\n NgpRangeSlider,\n NgpRangeSliderRange,\n NgpRangeSliderThumb,\n NgpRangeSliderTrack,\n provideRangeSliderState,\n} from 'ng-primitives/slider';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\nimport { merge } from 'rxjs';\n\n@Component({\n selector: 'app-range-slider',\n hostDirectives: [\n {\n directive: NgpRangeSlider,\n inputs: [\n 'ngpRangeSliderLow:low',\n 'ngpRangeSliderHigh:high',\n 'ngpRangeSliderMin:min',\n 'ngpRangeSliderMax:max',\n 'ngpRangeSliderStep:step',\n 'ngpRangeSliderDisabled:disabled',\n 'ngpRangeSliderOrientation:orientation',\n ],\n outputs: ['ngpRangeSliderLowChange:lowChange', 'ngpRangeSliderHighChange:highChange'],\n },\n ],\n imports: [NgpRangeSliderTrack, NgpRangeSliderRange, NgpRangeSliderThumb],\n providers: [provideRangeSliderState(), provideValueAccessor(RangeSlider)],\n template: `\n <div ngpRangeSliderTrack>\n <div ngpRangeSliderRange></div>\n </div>\n <div ngpRangeSliderThumb></div>\n <div ngpRangeSliderThumb></div>\n `,\n styles: `\n :host {\n display: flex;\n position: relative;\n width: 200px;\n height: 20px;\n touch-action: none;\n user-select: none;\n align-items: center;\n }\n\n [ngpRangeSliderTrack] {\n position: relative;\n height: 5px;\n width: 100%;\n border-radius: 999px;\n background-color: var(--ngp-background-secondary);\n }\n\n [ngpRangeSliderRange] {\n position: absolute;\n height: 100%;\n border-radius: 999px;\n background-color: var(--ngp-background-inverse);\n }\n\n [ngpRangeSliderThumb] {\n position: absolute;\n display: block;\n height: 20px;\n width: 20px;\n border-radius: 10px;\n background-color: white;\n box-shadow: var(--ngp-button-shadow);\n outline: none;\n transform: translateX(-50%);\n }\n\n [ngpRangeSliderThumb][data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 0;\n }\n\n [ngpRangeSliderThumb][data-thumb='high'] {\n z-index: 2;\n }\n `,\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class RangeSlider implements ControlValueAccessor {\n /** Access the range slider state */\n private readonly state = injectRangeSliderState();\n\n /** Forward aria-labels to each thumb */\n readonly ariaLabelLow = input<string | null>(null);\n readonly ariaLabelHigh = input<string | null>(null);\n\n /** The onChange callback function. */\n private onChange?: ChangeFn<[number, number]>;\n\n /** The onTouched callback function. */\n protected onTouched?: TouchedFn;\n\n constructor() {\n // Whenever either value changes, call the onChange function with the new tuple [low, high].\n merge(this.state().lowChange, this.state().highChange)\n .pipe(takeUntilDestroyed())\n .subscribe(() => this.onChange?.([this.state().low(), this.state().high()]));\n }\n\n writeValue(value: [number, number]): void {\n if (!value || value.length !== 2) {\n return;\n }\n\n const [low, high] = value;\n // Use the directive's clamping setters to respect min/max and ordering\n this.state().setLowValue(low);\n this.state().setHighValue(high);\n }\n\n registerOnChange(fn: ChangeFn<[number, number]>): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.state().setDisabled(isDisabled);\n }\n}\n",
|
|
151
|
+
"code": "import { Component, input } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor } from '@angular/forms';\nimport {\n injectRangeSliderState,\n NgpRangeSlider,\n NgpRangeSliderRange,\n NgpRangeSliderThumb,\n NgpRangeSliderTrack,\n provideRangeSliderState,\n} from 'ng-primitives/slider';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\nimport { merge } from 'rxjs';\n\n@Component({\n selector: 'app-range-slider',\n hostDirectives: [\n {\n directive: NgpRangeSlider,\n inputs: [\n 'ngpRangeSliderLow:low',\n 'ngpRangeSliderHigh:high',\n 'ngpRangeSliderMin:min',\n 'ngpRangeSliderMax:max',\n 'ngpRangeSliderStep:step',\n 'ngpRangeSliderDisabled:disabled',\n 'ngpRangeSliderOrientation:orientation',\n ],\n outputs: ['ngpRangeSliderLowChange:lowChange', 'ngpRangeSliderHighChange:highChange'],\n },\n ],\n imports: [NgpRangeSliderTrack, NgpRangeSliderRange, NgpRangeSliderThumb],\n providers: [provideRangeSliderState(), provideValueAccessor(RangeSlider)],\n template: `\n <div ngpRangeSliderTrack>\n <div ngpRangeSliderRange></div>\n </div>\n <div ngpRangeSliderThumb></div>\n <div ngpRangeSliderThumb></div>\n `,\n styles: `\n :host {\n display: flex;\n position: relative;\n width: 200px;\n height: 20px;\n touch-action: none;\n user-select: none;\n align-items: center;\n }\n\n [ngpRangeSliderTrack] {\n position: relative;\n height: 5px;\n width: 100%;\n border-radius: 999px;\n background-color: var(--ngp-background-secondary);\n }\n\n [ngpRangeSliderRange] {\n position: absolute;\n height: 100%;\n border-radius: 999px;\n background-color: var(--ngp-background-inverse);\n }\n\n [ngpRangeSliderThumb] {\n position: absolute;\n display: block;\n height: 20px;\n width: 20px;\n border-radius: 10px;\n background-color: white;\n box-shadow: var(--ngp-button-shadow);\n outline: none;\n transform: translateX(-50%);\n }\n\n [ngpRangeSliderThumb][data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 0;\n }\n\n [ngpRangeSliderThumb][data-thumb='high'] {\n z-index: 2;\n }\n `,\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class RangeSlider implements ControlValueAccessor {\n /** Access the range slider state */\n private readonly state = injectRangeSliderState();\n\n /** Forward aria-labels to each thumb */\n readonly ariaLabelLow = input<string | null>(null);\n readonly ariaLabelHigh = input<string | null>(null);\n\n /** The onChange callback function. */\n private onChange?: ChangeFn<[number, number]>;\n\n /** The onTouched callback function. */\n protected onTouched?: TouchedFn;\n\n constructor() {\n // Whenever either value changes, call the onChange function with the new tuple [low, high].\n merge(this.state().lowChange, this.state().highChange)\n .pipe(takeUntilDestroyed())\n .subscribe(() => this.onChange?.([this.state().low(), this.state().high()]));\n }\n\n writeValue(value: [number, number]): void {\n if (!value || value.length !== 2) {\n return;\n }\n\n const [low, high] = value;\n // Use the directive's clamping setters to respect min/max and ordering.\n // writing a value from the model must not re-emit through onChange\n this.state().setLowValue(low, { emit: false });\n this.state().setHighValue(high, { emit: false });\n }\n\n registerOnChange(fn: ChangeFn<[number, number]>): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.state().setDisabled(isDisabled);\n }\n}\n",
|
|
152
152
|
"primitive": "range-slider",
|
|
153
153
|
"hasVariants": false,
|
|
154
154
|
"hasSizes": false
|
|
@@ -176,14 +176,14 @@
|
|
|
176
176
|
},
|
|
177
177
|
{
|
|
178
178
|
"name": "slider",
|
|
179
|
-
"code": "import { Component, input } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor } from '@angular/forms';\nimport {\n injectSliderState,\n NgpSlider,\n NgpSliderRange,\n NgpSliderThumb,\n NgpSliderTrack,\n} from 'ng-primitives/slider';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-slider',\n hostDirectives: [\n {\n directive: NgpSlider,\n inputs: [\n 'ngpSliderValue:value',\n 'ngpSliderMin:min',\n 'ngpSliderMax:max',\n 'ngpSliderDisabled:disabled',\n ],\n outputs: ['ngpSliderValueChange:valueChange'],\n },\n ],\n imports: [NgpSliderTrack, NgpSliderRange, NgpSliderThumb],\n providers: [provideValueAccessor(Slider)],\n template: `\n <div ngpSliderTrack>\n <div ngpSliderRange></div>\n </div>\n <div [ariaLabel]=\"ariaLabel()\" ngpSliderThumb></div>\n `,\n styles: `\n :host {\n display: flex;\n position: relative;\n width: 200px;\n height: 20px;\n touch-action: none;\n user-select: none;\n align-items: center;\n }\n\n [ngpSliderTrack] {\n position: relative;\n height: 5px;\n width: 100%;\n border-radius: 999px;\n background-color: var(--ngp-background-secondary);\n }\n\n [ngpSliderRange] {\n position: absolute;\n height: 100%;\n border-radius: 999px;\n background-color: var(--ngp-background-inverse);\n }\n\n [ngpSliderThumb] {\n position: absolute;\n display: block;\n height: 20px;\n width: 20px;\n border-radius: 10px;\n background-color: white;\n box-shadow: var(--ngp-button-shadow);\n outline: none;\n transform: translateX(-50%);\n }\n\n [ngpSliderThumb][data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 0;\n }\n `,\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class Slider implements ControlValueAccessor {\n /** Access the slider state */\n private readonly state = injectSliderState();\n\n /** Forward the aria-label to the thumb */\n readonly ariaLabel = input<string | null>(null, {\n alias: 'aria-label',\n });\n\n /**\n * The onChange callback function.\n */\n private onChange?: ChangeFn<number>;\n\n /**\n * The onTouched callback function.\n */\n protected onTouched?: TouchedFn;\n\n constructor() {\n // Whenever the user interacts with the slider, call the onChange function with the new value.\n this.state()\n .valueChange.pipe(takeUntilDestroyed())\n .subscribe(value => this.onChange?.(value));\n }\n\n writeValue(value: number): void {\n this.state().setValue(value);\n }\n\n registerOnChange(fn: ChangeFn<number>): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.state().setDisabled(isDisabled);\n }\n}\n",
|
|
179
|
+
"code": "import { Component, input } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor } from '@angular/forms';\nimport {\n injectSliderState,\n NgpSlider,\n NgpSliderRange,\n NgpSliderThumb,\n NgpSliderTrack,\n} from 'ng-primitives/slider';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-slider',\n hostDirectives: [\n {\n directive: NgpSlider,\n inputs: [\n 'ngpSliderValue:value',\n 'ngpSliderMin:min',\n 'ngpSliderMax:max',\n 'ngpSliderDisabled:disabled',\n ],\n outputs: ['ngpSliderValueChange:valueChange'],\n },\n ],\n imports: [NgpSliderTrack, NgpSliderRange, NgpSliderThumb],\n providers: [provideValueAccessor(Slider)],\n template: `\n <div ngpSliderTrack>\n <div ngpSliderRange></div>\n </div>\n <div [ariaLabel]=\"ariaLabel()\" ngpSliderThumb></div>\n `,\n styles: `\n :host {\n display: flex;\n position: relative;\n width: 200px;\n height: 20px;\n touch-action: none;\n user-select: none;\n align-items: center;\n }\n\n [ngpSliderTrack] {\n position: relative;\n height: 5px;\n width: 100%;\n border-radius: 999px;\n background-color: var(--ngp-background-secondary);\n }\n\n [ngpSliderRange] {\n position: absolute;\n height: 100%;\n border-radius: 999px;\n background-color: var(--ngp-background-inverse);\n }\n\n [ngpSliderThumb] {\n position: absolute;\n display: block;\n height: 20px;\n width: 20px;\n border-radius: 10px;\n background-color: white;\n box-shadow: var(--ngp-button-shadow);\n outline: none;\n transform: translateX(-50%);\n }\n\n [ngpSliderThumb][data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 0;\n }\n `,\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class Slider implements ControlValueAccessor {\n /** Access the slider state */\n private readonly state = injectSliderState();\n\n /** Forward the aria-label to the thumb */\n readonly ariaLabel = input<string | null>(null, {\n alias: 'aria-label',\n });\n\n /**\n * The onChange callback function.\n */\n private onChange?: ChangeFn<number>;\n\n /**\n * The onTouched callback function.\n */\n protected onTouched?: TouchedFn;\n\n constructor() {\n // Whenever the user interacts with the slider, call the onChange function with the new value.\n this.state()\n .valueChange.pipe(takeUntilDestroyed())\n .subscribe(value => this.onChange?.(value));\n }\n\n writeValue(value: number): void {\n // writing a value from the model must not re-emit through onChange\n this.state().setValue(value, { emit: false });\n }\n\n registerOnChange(fn: ChangeFn<number>): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.state().setDisabled(isDisabled);\n }\n}\n",
|
|
180
180
|
"primitive": "slider",
|
|
181
181
|
"hasVariants": false,
|
|
182
182
|
"hasSizes": false
|
|
183
183
|
},
|
|
184
184
|
{
|
|
185
185
|
"name": "switch",
|
|
186
|
-
"code": "import { Component } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { injectSwitchState, NgpSwitch, NgpSwitchThumb } from 'ng-primitives/switch';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-switch',\n hostDirectives: [\n {\n directive: NgpSwitch,\n inputs: ['ngpSwitchChecked:checked', 'ngpSwitchDisabled:disabled'],\n outputs: ['ngpSwitchCheckedChange:checkedChange'],\n },\n ],\n imports: [NgpSwitchThumb],\n template: `\n <span ngpSwitchThumb></span>\n `,\n styles: `\n :host {\n display: inline-flex;\n align-items: center;\n position: relative;\n width: 2.5rem;\n height: 1.5rem;\n border-radius: 999px;\n background-color: var(--ngp-background-secondary);\n border: 1px solid var(--ngp-border);\n padding: 0;\n outline: none;\n transition-property:\n color, background-color, border-color, text-decoration-color, fill, stroke;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n box-sizing: border-box;\n }\n\n :host[data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n }\n\n :host[data-checked] {\n background-color: var(--ngp-background-blue);\n border-color: var(--ngp-border-blue);\n }\n\n [ngpSwitchThumb] {\n display: block;\n height: 1.25rem;\n width: 1.25rem;\n border-radius: 999px;\n background-color: white;\n box-shadow: var(--ngp-button-shadow);\n outline: none;\n transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1);\n transform: translateX(1px);\n box-sizing: border-box;\n }\n\n [ngpSwitchThumb][data-checked] {\n transform: translateX(17px);\n }\n `,\n providers: [provideValueAccessor(Switch)],\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class Switch implements ControlValueAccessor {\n /** Access the switch state. */\n private readonly switch = injectSwitchState();\n\n /** The on change callback */\n private onChange?: ChangeFn<boolean>;\n\n /** The on touched callback */\n protected onTouched?: TouchedFn;\n\n constructor() {\n // Any time the switch changes, update the form value.\n this.switch()\n .checkedChange.pipe(takeUntilDestroyed())\n .subscribe(value => this.onChange?.(value));\n }\n\n /** Write a new value to the switch. */\n writeValue(value: boolean): void {\n this.switch().setChecked(value);\n }\n\n /** Register a callback function to be called when the value changes. */\n registerOnChange(fn: ChangeFn<boolean>): void {\n this.onChange = fn;\n }\n\n /** Register a callback function to be called when the switch is touched. */\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n /** Set the disabled state of the switch. */\n setDisabledState(isDisabled: boolean): void {\n this.switch().setDisabled(isDisabled);\n }\n}\n",
|
|
186
|
+
"code": "import { Component } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { injectSwitchState, NgpSwitch, NgpSwitchThumb } from 'ng-primitives/switch';\nimport { ChangeFn, provideValueAccessor, TouchedFn } from 'ng-primitives/utils';\n\n@Component({\n selector: 'app-switch',\n hostDirectives: [\n {\n directive: NgpSwitch,\n inputs: ['ngpSwitchChecked:checked', 'ngpSwitchDisabled:disabled'],\n outputs: ['ngpSwitchCheckedChange:checkedChange'],\n },\n ],\n imports: [NgpSwitchThumb],\n template: `\n <span ngpSwitchThumb></span>\n `,\n styles: `\n :host {\n display: inline-flex;\n align-items: center;\n position: relative;\n width: 2.5rem;\n height: 1.5rem;\n border-radius: 999px;\n background-color: var(--ngp-background-secondary);\n border: 1px solid var(--ngp-border);\n padding: 0;\n outline: none;\n transition-property:\n color, background-color, border-color, text-decoration-color, fill, stroke;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n box-sizing: border-box;\n }\n\n :host[data-focus-visible] {\n outline: 2px solid var(--ngp-focus-ring);\n }\n\n :host[data-checked] {\n background-color: var(--ngp-background-blue);\n border-color: var(--ngp-border-blue);\n }\n\n [ngpSwitchThumb] {\n display: block;\n height: 1.25rem;\n width: 1.25rem;\n border-radius: 999px;\n background-color: white;\n box-shadow: var(--ngp-button-shadow);\n outline: none;\n transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1);\n transform: translateX(1px);\n box-sizing: border-box;\n }\n\n [ngpSwitchThumb][data-checked] {\n transform: translateX(17px);\n }\n `,\n providers: [provideValueAccessor(Switch)],\n host: {\n '(focusout)': 'onTouched?.()',\n },\n})\nexport class Switch implements ControlValueAccessor {\n /** Access the switch state. */\n private readonly switch = injectSwitchState();\n\n /** The on change callback */\n private onChange?: ChangeFn<boolean>;\n\n /** The on touched callback */\n protected onTouched?: TouchedFn;\n\n constructor() {\n // Any time the switch changes, update the form value.\n this.switch()\n .checkedChange.pipe(takeUntilDestroyed())\n .subscribe(value => this.onChange?.(value));\n }\n\n /** Write a new value to the switch. */\n writeValue(value: boolean): void {\n // writing a value from the model must not re-emit through onChange\n this.switch().setChecked(value, { emit: false });\n }\n\n /** Register a callback function to be called when the value changes. */\n registerOnChange(fn: ChangeFn<boolean>): void {\n this.onChange = fn;\n }\n\n /** Register a callback function to be called when the switch is touched. */\n registerOnTouched(fn: TouchedFn): void {\n this.onTouched = fn;\n }\n\n /** Set the disabled state of the switch. */\n setDisabledState(isDisabled: boolean): void {\n this.switch().setDisabled(isDisabled);\n }\n}\n",
|
|
187
187
|
"primitive": "switch",
|
|
188
188
|
"hasVariants": false,
|
|
189
189
|
"hasSizes": false
|