@ng-primitives/mcp 0.111.1 → 0.112.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-primitives/mcp",
3
- "version": "0.111.1",
3
+ "version": "0.112.0",
4
4
  "description": "MCP server for Angular Primitives - headless UI library",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -2004,6 +2004,102 @@
2004
2004
  ],
2005
2005
  "outputs": []
2006
2006
  },
2007
+ "NgpNumberFieldIncrement": {
2008
+ "name": "NgpNumberFieldIncrement",
2009
+ "description": "Apply the `ngpNumberFieldIncrement` directive to a button element that increments the number field value.",
2010
+ "selector": "[ngpNumberFieldIncrement]",
2011
+ "exportAs": [
2012
+ "ngpNumberFieldIncrement"
2013
+ ],
2014
+ "inputs": [],
2015
+ "outputs": []
2016
+ },
2017
+ "NgpNumberFieldDecrement": {
2018
+ "name": "NgpNumberFieldDecrement",
2019
+ "description": "Apply the `ngpNumberFieldDecrement` directive to a button element that decrements the number field value.",
2020
+ "selector": "[ngpNumberFieldDecrement]",
2021
+ "exportAs": [
2022
+ "ngpNumberFieldDecrement"
2023
+ ],
2024
+ "inputs": [],
2025
+ "outputs": []
2026
+ },
2027
+ "NgpNumberFieldInput": {
2028
+ "name": "NgpNumberFieldInput",
2029
+ "description": "Apply the `ngpNumberFieldInput` directive to an input element within a number field.",
2030
+ "selector": "[ngpNumberFieldInput]",
2031
+ "exportAs": [
2032
+ "ngpNumberFieldInput"
2033
+ ],
2034
+ "inputs": [
2035
+ {
2036
+ "name": "ngpNumberFieldInputAllowWheelScrub",
2037
+ "type": "boolean",
2038
+ "description": "Whether mouse wheel changes the value when the input is focused.",
2039
+ "isRequired": false
2040
+ }
2041
+ ],
2042
+ "outputs": []
2043
+ },
2044
+ "NgpNumberField": {
2045
+ "name": "NgpNumberField",
2046
+ "description": "Apply the `ngpNumberField` directive to an element that represents the number field\nand contains the input, increment, and decrement buttons.",
2047
+ "selector": "[ngpNumberField]",
2048
+ "exportAs": [
2049
+ "ngpNumberField"
2050
+ ],
2051
+ "inputs": [
2052
+ {
2053
+ "name": "ngpNumberFieldValue",
2054
+ "type": "number | null",
2055
+ "description": "The value of the number field.",
2056
+ "isRequired": false
2057
+ },
2058
+ {
2059
+ "name": "ngpNumberFieldMin",
2060
+ "type": "number",
2061
+ "description": "The minimum value.",
2062
+ "isRequired": false
2063
+ },
2064
+ {
2065
+ "name": "ngpNumberFieldMax",
2066
+ "type": "number",
2067
+ "description": "The maximum value.",
2068
+ "isRequired": false
2069
+ },
2070
+ {
2071
+ "name": "ngpNumberFieldStep",
2072
+ "type": "number",
2073
+ "description": "The step value.",
2074
+ "isRequired": false
2075
+ },
2076
+ {
2077
+ "name": "ngpNumberFieldLargeStep",
2078
+ "type": "number",
2079
+ "description": "The large step value (used with Shift key).",
2080
+ "isRequired": false
2081
+ },
2082
+ {
2083
+ "name": "ngpNumberFieldDisabled",
2084
+ "type": "boolean",
2085
+ "description": "The disabled state of the number field.",
2086
+ "isRequired": false
2087
+ },
2088
+ {
2089
+ "name": "ngpNumberFieldReadonly",
2090
+ "type": "boolean",
2091
+ "description": "The readonly state of the number field.",
2092
+ "isRequired": false
2093
+ }
2094
+ ],
2095
+ "outputs": [
2096
+ {
2097
+ "name": "ngpNumberFieldValueChange",
2098
+ "type": "number | null",
2099
+ "description": "Emits when the value changes."
2100
+ }
2101
+ ]
2102
+ },
2007
2103
  "NgpPagination": {
2008
2104
  "name": "NgpPagination",
2009
2105
  "description": "The `NgpPagination` directive is used to create a pagination control.",
@@ -945,6 +945,59 @@
945
945
  }
946
946
  ]
947
947
  },
948
+ {
949
+ "name": "number-field",
950
+ "entryPoint": "ng-primitives/number-field",
951
+ "exports": [
952
+ "NgpNumberField",
953
+ "injectNumberFieldState",
954
+ "ngpNumberField",
955
+ "NgpNumberFieldProps",
956
+ "NgpNumberFieldState",
957
+ "provideNumberFieldState",
958
+ "NgpNumberFieldInput",
959
+ "injectNumberFieldInputState",
960
+ "ngpNumberFieldInput",
961
+ "NgpNumberFieldInputProps",
962
+ "NgpNumberFieldInputState",
963
+ "provideNumberFieldInputState",
964
+ "NgpNumberFieldIncrement",
965
+ "injectNumberFieldIncrementState",
966
+ "ngpNumberFieldIncrement",
967
+ "NgpNumberFieldIncrementProps",
968
+ "NgpNumberFieldIncrementState",
969
+ "provideNumberFieldIncrementState",
970
+ "NgpNumberFieldDecrement",
971
+ "injectNumberFieldDecrementState",
972
+ "ngpNumberFieldDecrement",
973
+ "NgpNumberFieldDecrementProps",
974
+ "NgpNumberFieldDecrementState",
975
+ "provideNumberFieldDecrementState"
976
+ ],
977
+ "hasSecondaryEntryPoint": true,
978
+ "category": "utility",
979
+ "description": "A numeric input with increment and decrement buttons.",
980
+ "accessibility": [
981
+ "ARIA design"
982
+ ],
983
+ "examples": [
984
+ {
985
+ "name": "example-0",
986
+ "code": "import {\n NgpNumberField,\n NgpNumberFieldInput,\n NgpNumberFieldIncrement,\n NgpNumberFieldDecrement,\n} from 'ng-primitives/number-field';",
987
+ "description": "Import"
988
+ },
989
+ {
990
+ "name": "example-1",
991
+ "code": "<div ngpNumberField>\n <button ngpNumberFieldDecrement>−</button>\n <input ngpNumberFieldInput />\n <button ngpNumberFieldIncrement>+</button>\n</div>",
992
+ "description": "Usage"
993
+ }
994
+ ],
995
+ "reusableComponent": {
996
+ "code": "import { Component } from '@angular/core';\nimport {\n NgpNumberField,\n NgpNumberFieldDecrement,\n NgpNumberFieldIncrement,\n NgpNumberFieldInput,\n} from 'ng-primitives/number-field';\n\n@Component({\n selector: 'app-number-field',\n hostDirectives: [\n {\n directive: NgpNumberField,\n inputs: [\n 'ngpNumberFieldValue:value',\n 'ngpNumberFieldMin:min',\n 'ngpNumberFieldMax:max',\n 'ngpNumberFieldStep:step',\n 'ngpNumberFieldLargeStep:largeStep',\n 'ngpNumberFieldDisabled:disabled',\n 'ngpNumberFieldReadonly:readonly',\n ],\n outputs: ['ngpNumberFieldValueChange:valueChange'],\n },\n ],\n imports: [NgpNumberFieldInput, NgpNumberFieldIncrement, NgpNumberFieldDecrement],\n template: `\n <button ngpNumberFieldDecrement aria-label=\"Decrement\">−</button>\n <input ngpNumberFieldInput />\n <button ngpNumberFieldIncrement aria-label=\"Increment\">+</button>\n `,\n styles: `\n :host {\n display: inline-flex;\n align-items: center;\n border-radius: 8px;\n box-shadow: var(--ngp-input-shadow);\n background-color: var(--ngp-background);\n overflow: hidden;\n }\n\n :host:focus-within {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 2px;\n }\n\n [ngpNumberFieldInput] {\n width: 64px;\n height: 36px;\n border: none;\n outline: none;\n text-align: center;\n font-size: 0.875rem;\n color: var(--ngp-text-primary);\n background: transparent;\n box-sizing: border-box;\n padding: 0;\n }\n\n [ngpNumberFieldInput]::placeholder {\n color: var(--ngp-text-placeholder);\n }\n\n [ngpNumberFieldIncrement],\n [ngpNumberFieldDecrement] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n border: none;\n background: transparent;\n color: var(--ngp-text-secondary);\n cursor: pointer;\n font-size: 1rem;\n user-select: none;\n -webkit-touch-callout: none;\n transition:\n color 150ms ease,\n background-color 150ms ease;\n }\n\n [ngpNumberFieldIncrement][data-hover],\n [ngpNumberFieldDecrement][data-hover] {\n background-color: var(--ngp-background-hover);\n color: var(--ngp-text-primary);\n }\n\n [ngpNumberFieldIncrement][data-press],\n [ngpNumberFieldDecrement][data-press] {\n background-color: var(--ngp-background-active);\n }\n\n [ngpNumberFieldIncrement][data-disabled],\n [ngpNumberFieldDecrement][data-disabled] {\n opacity: 0.4;\n cursor: not-allowed;\n }\n\n [ngpNumberFieldIncrement][data-disabled][data-hover],\n [ngpNumberFieldDecrement][data-disabled][data-hover] {\n background: transparent;\n color: var(--ngp-text-secondary);\n }\n `,\n})\nexport class NumberField {}\n",
997
+ "hasVariants": false,
998
+ "hasSizes": true
999
+ }
1000
+ },
948
1001
  {
949
1002
  "name": "pagination",
950
1003
  "entryPoint": "ng-primitives/pagination",
@@ -104,6 +104,13 @@
104
104
  "hasVariants": false,
105
105
  "hasSizes": true
106
106
  },
107
+ {
108
+ "name": "number-field",
109
+ "code": "import { Component } from '@angular/core';\nimport {\n NgpNumberField,\n NgpNumberFieldDecrement,\n NgpNumberFieldIncrement,\n NgpNumberFieldInput,\n} from 'ng-primitives/number-field';\n\n@Component({\n selector: 'app-number-field',\n hostDirectives: [\n {\n directive: NgpNumberField,\n inputs: [\n 'ngpNumberFieldValue:value',\n 'ngpNumberFieldMin:min',\n 'ngpNumberFieldMax:max',\n 'ngpNumberFieldStep:step',\n 'ngpNumberFieldLargeStep:largeStep',\n 'ngpNumberFieldDisabled:disabled',\n 'ngpNumberFieldReadonly:readonly',\n ],\n outputs: ['ngpNumberFieldValueChange:valueChange'],\n },\n ],\n imports: [NgpNumberFieldInput, NgpNumberFieldIncrement, NgpNumberFieldDecrement],\n template: `\n <button ngpNumberFieldDecrement aria-label=\"Decrement\">−</button>\n <input ngpNumberFieldInput />\n <button ngpNumberFieldIncrement aria-label=\"Increment\">+</button>\n `,\n styles: `\n :host {\n display: inline-flex;\n align-items: center;\n border-radius: 8px;\n box-shadow: var(--ngp-input-shadow);\n background-color: var(--ngp-background);\n overflow: hidden;\n }\n\n :host:focus-within {\n outline: 2px solid var(--ngp-focus-ring);\n outline-offset: 2px;\n }\n\n [ngpNumberFieldInput] {\n width: 64px;\n height: 36px;\n border: none;\n outline: none;\n text-align: center;\n font-size: 0.875rem;\n color: var(--ngp-text-primary);\n background: transparent;\n box-sizing: border-box;\n padding: 0;\n }\n\n [ngpNumberFieldInput]::placeholder {\n color: var(--ngp-text-placeholder);\n }\n\n [ngpNumberFieldIncrement],\n [ngpNumberFieldDecrement] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n border: none;\n background: transparent;\n color: var(--ngp-text-secondary);\n cursor: pointer;\n font-size: 1rem;\n user-select: none;\n -webkit-touch-callout: none;\n transition:\n color 150ms ease,\n background-color 150ms ease;\n }\n\n [ngpNumberFieldIncrement][data-hover],\n [ngpNumberFieldDecrement][data-hover] {\n background-color: var(--ngp-background-hover);\n color: var(--ngp-text-primary);\n }\n\n [ngpNumberFieldIncrement][data-press],\n [ngpNumberFieldDecrement][data-press] {\n background-color: var(--ngp-background-active);\n }\n\n [ngpNumberFieldIncrement][data-disabled],\n [ngpNumberFieldDecrement][data-disabled] {\n opacity: 0.4;\n cursor: not-allowed;\n }\n\n [ngpNumberFieldIncrement][data-disabled][data-hover],\n [ngpNumberFieldDecrement][data-disabled][data-hover] {\n background: transparent;\n color: var(--ngp-text-secondary);\n }\n `,\n})\nexport class NumberField {}\n",
110
+ "primitive": "number-field",
111
+ "hasVariants": false,
112
+ "hasSizes": true
113
+ },
107
114
  {
108
115
  "name": "pagination",
109
116
  "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().page.set(value);\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",