@ngstarter-ui/components 1.0.34 → 1.0.35
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.
|
@@ -4905,8 +4905,8 @@
|
|
|
4905
4905
|
"sourceRoot": "projects/components/input-mask/src",
|
|
4906
4906
|
"docsPath": "/forms/input-mask",
|
|
4907
4907
|
"docsOverviewSource": "projects/docs/src/app/forms/input-mask/overview/overview.html",
|
|
4908
|
-
"purpose": "
|
|
4909
|
-
"useWhen": "Use for
|
|
4908
|
+
"purpose": "Format credit card input fields while the user types with ready-made mask directives.",
|
|
4909
|
+
"useWhen": "Use on native inputs, usually with ngsInput inside ngs-form-field, for payment or billing fields that need credit card formatting. Available directives are ngsCreditCardNumberMask for grouped card numbers, ngsCreditCardExpiryDateMask for MM/YY expiry, and ngsCreditCardCvvMask for CVV/CVC. The directives format the visible input, set useful mobile keyboard and autocomplete attributes where applicable, and keep the Angular form value cleaned for card number and expiry. Do not use as a universal mask engine, validator, payment security layer, or compliance solution. Do not use for phone numbers; use PhoneInput. Do not use for custom IDs, tax numbers, IBAN, postal codes, arbitrary structured text, date pickers, selects, currency fields, country fields, or formatting saved display values; use dedicated components, validators, backend checks, or a custom mask directive.",
|
|
4910
4910
|
"exampleTopics": [
|
|
4911
4911
|
"Credit card number input mask",
|
|
4912
4912
|
"Credit card expiry date input mask",
|
|
@@ -4964,16 +4964,19 @@
|
|
|
4964
4964
|
"sourceRoot": "projects/components/input-validator/src",
|
|
4965
4965
|
"docsPath": "/forms/input-validator",
|
|
4966
4966
|
"docsOverviewSource": "projects/docs/src/app/forms/input-validator/overview/overview.html",
|
|
4967
|
-
"purpose": "
|
|
4968
|
-
"useWhen": "Use
|
|
4967
|
+
"purpose": "Provide ready-made Angular ValidatorFn helpers for common reusable form validation rules.",
|
|
4968
|
+
"useWhen": "Use in reactive forms with ngs-form-field, ngsInput, Angular Validators, and ngs-error when a preset client-side validator fits. Current payment presets include creditCardNumberValidator() for cleaned card number length and Luhn checksum, expiryDateValidator() for MMYY expiry format, valid month, and not-in-past checks, and creditCardCvvValidator() for numeric CVV/CVC length with optional minLength and maxLength. Pair these validators with InputMask directives when the user also needs formatted payment input. Do not use InputValidator as a UI component, input formatter, input mask, replacement for Angular built-in validators, backend validation, payment processor validation, or security/compliance layer. Do not use for arbitrary custom business rules unless a dedicated preset exists; write a project validator.",
|
|
4969
4969
|
"exampleTopics": [
|
|
4970
|
-
"Credit card input
|
|
4970
|
+
"Credit card input validators"
|
|
4971
4971
|
],
|
|
4972
4972
|
"minimalExample": null,
|
|
4973
4973
|
"exampleFiles": [],
|
|
4974
4974
|
"previewAsset": "projects/components/input-validator/preview.svg",
|
|
4975
4975
|
"selectors": [],
|
|
4976
4976
|
"exportedSymbols": [
|
|
4977
|
+
"creditCardCvvValidator",
|
|
4978
|
+
"CreditCardCvvValidatorOptions",
|
|
4979
|
+
"creditCardNumberValidator",
|
|
4977
4980
|
"expiryDateValidator"
|
|
4978
4981
|
],
|
|
4979
4982
|
"inputs": [],
|
|
@@ -4992,9 +4995,11 @@
|
|
|
4992
4995
|
"sourceRoot": "projects/components/kanban-board/src",
|
|
4993
4996
|
"docsPath": "/libraries/kanban-board",
|
|
4994
4997
|
"docsOverviewSource": "projects/docs/src/app/libraries/kanban-board/overview/overview.html",
|
|
4995
|
-
"purpose": "
|
|
4996
|
-
"useWhen": "Use for tasks, deals,
|
|
4997
|
-
"exampleTopics": [
|
|
4998
|
+
"purpose": "Render a horizontal workflow board with status columns and draggable cards.",
|
|
4999
|
+
"useWhen": "Use ngs-kanban-board for tasks, issues, CRM deals, hiring pipelines, content workflows, support tickets, and other status-based boards where users drag items within a column or between columns. Provide columns with id, name, color, and items; each item should include at least name and position. Render cards through a custom ngsKanbanItemDef template and compose card content with NgStarter components such as Avatar, Badge, Icon, Button, and text. The board mutates local arrays with CDK moveItemInArray and transferArrayItem and emits itemSorted, itemTransferred, itemDropped, itemClick, itemAdd, columnEdit, and columnDelete; the app must persist the new order, status, and business data to the backend. Do not use for simple record tables; use Table or DataView. Do not use for static lists; use List. Do not use for dashboard widget layouts; use Grid. Do not use for calendars, timelines, arbitrary drag-and-drop builders, or screens without real workflow/status columns.",
|
|
5000
|
+
"exampleTopics": [
|
|
5001
|
+
"Kanban Board"
|
|
5002
|
+
],
|
|
4998
5003
|
"minimalExample": null,
|
|
4999
5004
|
"exampleFiles": [],
|
|
5000
5005
|
"previewAsset": "projects/components/kanban-board/preview.svg",
|
|
@@ -5042,8 +5047,8 @@
|
|
|
5042
5047
|
"sourceRoot": "projects/components/kbd/src",
|
|
5043
5048
|
"docsPath": "/components/kbd",
|
|
5044
5049
|
"docsOverviewSource": "projects/docs/src/app/components/kdb/overview/overview.html",
|
|
5045
|
-
"purpose": "
|
|
5046
|
-
"useWhen": "Use in help text,
|
|
5050
|
+
"purpose": "Display visual keyboard keys and shortcut hints.",
|
|
5051
|
+
"useWhen": "Use ngs-kbd for a single key such as Cmd, Shift, K, Esc, or an arrow key, and ngs-kbd-group for key combinations with plus signs between keys. Use in menus, command palettes, toolbars, help text, onboarding, documentation, and shortcut hints next to commands. Kbd is visual only: it does not register shortcuts, handle keyboard events, trigger actions, or provide command logic. Do not use as a clickable button; use Button or IconButton. Do not use for statuses or counts; use Badge. Do not use for tags or categories; use Chips. Do not use as normal body text or for actions that do not have a real shortcut handled elsewhere.",
|
|
5047
5052
|
"exampleTopics": [
|
|
5048
5053
|
"Basic Keyboard",
|
|
5049
5054
|
"Keyboard group",
|
|
@@ -5102,8 +5107,8 @@
|
|
|
5102
5107
|
"sourceRoot": "projects/components/layout/src",
|
|
5103
5108
|
"docsPath": "/components/layout",
|
|
5104
5109
|
"docsOverviewSource": "projects/docs/src/app/components/layout/overview/overview.html",
|
|
5105
|
-
"purpose": "
|
|
5106
|
-
"useWhen": "Use for
|
|
5110
|
+
"purpose": "Provide the base top-level shell for an application, admin area, dashboard, or large workspace page.",
|
|
5111
|
+
"useWhen": "Use ngs-layout as the outer structural frame when the whole screen needs topbar, header, sidebar, scrollable content, aside, or footer regions. Use root for a full viewport application shell. Use ngs-layout-content for the main scroll container, and LayoutApiService with layoutId when the sidebar must be shown, hidden, or toggled. Nested layouts are appropriate when a large app shell contains another structured workspace with its own header/content/footer. Do not use Layout as a small wrapper, card, spacing helper, form grouping tool, or generic grid system. Use TailwindCSS grid, flex, and spacing classes inside layout regions. Use Grid for dashboard widgets, DataView or Table for datasets, Drawer for overlay side panels, and Navigation, Sidebar, or Sidenav components inside sidebars.",
|
|
5107
5112
|
"exampleTopics": [
|
|
5108
5113
|
"Layout header",
|
|
5109
5114
|
"Layout sidebar",
|
|
@@ -5183,8 +5188,8 @@
|
|
|
5183
5188
|
"sourceRoot": "projects/components/list/src",
|
|
5184
5189
|
"docsPath": "/components/list",
|
|
5185
5190
|
"docsOverviewSource": "projects/docs/src/app/components/list/overview/overview.html",
|
|
5186
|
-
"purpose": "Display
|
|
5187
|
-
"useWhen": "Use
|
|
5191
|
+
"purpose": "Display a vertical group of related rows with consistent icon, avatar, title, line, meta, action, and selection structure.",
|
|
5192
|
+
"useWhen": "Use ngs-list with ngs-list-item for settings rows, files, messages, activity feed items, compact collections, simple action rows, and small repeated row groups. Use ngs-selection-list with ngs-list-option when users choose one or more rows. Use ngs-nav-list for simple navigation rows in sidebars or compact navigation areas. Use ngs-action-list for vertical action groups that are not dropdown menus. Compose each row with ngsListItemIcon or ngsListItemAvatar, ngsListItemTitle, ngsListItemLine, and ngsListItemMeta. Do not use List for large tabular datasets, columns, sorting, pagination, or bulk operations; use Table or DataView. Do not use for trigger-based dropdown or context actions; use Menu. Do not use as a full app navigation system when Navigation fits better. Do not use as a generic layout container.",
|
|
5188
5193
|
"exampleTopics": [
|
|
5189
5194
|
"Basic List",
|
|
5190
5195
|
"List With Sections",
|
|
@@ -5299,8 +5304,8 @@
|
|
|
5299
5304
|
"sourceRoot": "projects/components/logo/src",
|
|
5300
5305
|
"docsPath": null,
|
|
5301
5306
|
"docsOverviewSource": null,
|
|
5302
|
-
"purpose": "Render
|
|
5303
|
-
"useWhen": "Use in app shells, headers, auth
|
|
5307
|
+
"purpose": "Render a product or brand logo as a composed mark, name, and optional description.",
|
|
5308
|
+
"useWhen": "Use ngs-logo or a[ngs-logo] in app shells, headers, sidebars, auth screens, splash screens, and branding areas. Compose it with ngs-logo-shape for the brand mark or image, ngs-logo-text for the product name with size small, default, or large, and ngs-logo-description for a short subtitle, version, or status. Use a[ngs-logo] when the logo navigates to the home page. Do not use Logo for user or team identity; use Avatar. Do not use for standalone action icons; use Icon inside Button or IconButton. Do not use for product thumbnails, decorative images, empty states, arbitrary SVG illustrations, or general image display.",
|
|
5304
5309
|
"exampleTopics": [],
|
|
5305
5310
|
"minimalExample": null,
|
|
5306
5311
|
"exampleFiles": [],
|
|
@@ -5347,8 +5352,8 @@
|
|
|
5347
5352
|
"sourceRoot": "projects/components/marquee/src",
|
|
5348
5353
|
"docsPath": "/components/marquee",
|
|
5349
5354
|
"docsOverviewSource": "projects/docs/src/app/components/marquee/overview/overview.html",
|
|
5350
|
-
"purpose": "
|
|
5351
|
-
"useWhen": "Use for
|
|
5355
|
+
"purpose": "Display an infinite horizontal stream of repeated non-critical content.",
|
|
5356
|
+
"useWhen": "Use ngs-marquee for motion content that can move and repeat without losing meaning: promo text, short highlights, logos, badges, partner names, compact news, and decorative content showcases. Use reverse to change direction. Use pauseOnHover when users may need more time to read or interact with the moving content. Do not use Marquee for important system notices, errors, warnings, required actions, or content the user must read; use Announcement, Alert, ActionRequired, or Incidents. Do not use for navigation, tables, task lists, precise ticker data, forms, or interactive work surfaces.",
|
|
5352
5357
|
"exampleTopics": [
|
|
5353
5358
|
"Basic marquee",
|
|
5354
5359
|
"Marquee reverse",
|
|
@@ -5409,8 +5414,8 @@
|
|
|
5409
5414
|
"sourceRoot": "projects/components/menu/src",
|
|
5410
5415
|
"docsPath": "/components/menu",
|
|
5411
5416
|
"docsOverviewSource": "projects/docs/src/app/components/menu/overview/overview.html",
|
|
5412
|
-
"purpose": "Show contextual
|
|
5413
|
-
"useWhen": "Use for row actions, overflow
|
|
5417
|
+
"purpose": "Show a short contextual set of commands in an overlay opened from a trigger or right-click area.",
|
|
5418
|
+
"useWhen": "Use ngs-menu for row actions, overflow more actions, user menus, context menus, toolbar actions, and nested command groups. Put ngsMenuTriggerFor on a button ngsButton, button ngsIconButton, row action, or toolbar control. Use ngsContextMenuTriggerFor for right-click menus. Use button ngs-menu-item for commands, and ngs-menu-divider, ngs-menu-heading, ngs-menu-header, and ngs-menu-footer for structure. Use nested menus when a command opens a secondary command group. Use ngsMenuContent with ngsMenuTriggerData when the same menu template must render lazily for a specific row, user, or item. Do not use Menu for selecting form values; use Select, Autocomplete, ColorSwitcher, Datepicker, or another dedicated form control. Do not use for persistent navigation; use Navigation, Sidebar, Sidenav, or NavList. Do not use for long lists, tables, filters, forms, modal workflows, command palettes, or bulk action bars; use List, Table/DataView, Dialog, CommandBar, or Overlay/Popover as appropriate.",
|
|
5414
5419
|
"exampleTopics": [
|
|
5415
5420
|
"Basic Menu",
|
|
5416
5421
|
"Menu With Icons",
|
|
@@ -5555,8 +5560,8 @@
|
|
|
5555
5560
|
"sourceRoot": "projects/components/micro-chart/src",
|
|
5556
5561
|
"docsPath": "/micro-charts",
|
|
5557
5562
|
"docsOverviewSource": null,
|
|
5558
|
-
"purpose": "Render compact
|
|
5559
|
-
"useWhen": "Use
|
|
5563
|
+
"purpose": "Render compact line, bar, and pie charts for small trends, comparisons, and proportional breakdowns.",
|
|
5564
|
+
"useWhen": "Use ngs-mchart-line for a small trend over time or ordered values, ngs-mchart-bar for a compact comparison of several numeric values, and ngs-mchart-pie for a small proportional breakdown. Use MicroChart inside KPI cards, dashboard summaries, table cells, list rows, reports, and dense admin panels. It can also be used as a simple standalone dashboard chart when the chart type and level of detail match what MicroChart can display. Provide fixed dimensions with TailwindCSS classes such as w-*, h-*, or size-* because the chart renders inside its container. Use ngs-mchart-tooltip, ngs-mchart-tooltip-title, and ngs-mchart-tooltip-body when hover context is needed. Do not use MicroChart for complex analytics, detailed axes, advanced legends, drilldown, zooming, financial charting, or advanced interactions; use ECharts for complex charts. Do not use instead of ProgressBar or Gauge for a single progress percentage, Badge for status, or DataView/Table for tabular data.",
|
|
5560
5565
|
"exampleTopics": [],
|
|
5561
5566
|
"minimalExample": null,
|
|
5562
5567
|
"exampleFiles": [],
|
|
@@ -5655,8 +5660,8 @@
|
|
|
5655
5660
|
"sourceRoot": "projects/components/navigation/src",
|
|
5656
5661
|
"docsPath": "/navigation/navigation",
|
|
5657
5662
|
"docsOverviewSource": "projects/docs/src/app/navigation/nav/overview/overview.html",
|
|
5658
|
-
"purpose": "Render
|
|
5659
|
-
"useWhen": "Use
|
|
5663
|
+
"purpose": "Render a persistent product navigation structure when ngs-sidebar is not used.",
|
|
5664
|
+
"useWhen": "Use ngs-navigation for custom navigation areas, section navigation, settings navigation, admin navigation, and nested navigation groups when the screen needs product links but does not use ngs-sidebar. ngs-sidebar has its own navigation model, so do not duplicate ngs-navigation inside ngs-sidebar. Use ngs-navigation-item or [ngs-navigation-item] for destinations, key with activeKey for active state, activateByRoute for URL-based activation, autoScrollToActiveItem for long navigation, ngs-navigation-heading for sections, ngs-navigation-divider for group separation, and ngs-navigation-group with ngs-navigation-group-toggle and ngs-navigation-group-menu for expandable nested destinations. Use ngsNavigationItemIcon, ngsNavigationGroupToggleIcon, and ngsNavigationItemBadge for icons, toggles, and badges. Use dataSource with ngsNavigationItemDef when navigation comes from config or backend data. Do not use Navigation for trigger-based action menus; use Menu. Do not use for ordinary row lists; use List or NavList. Do not use for breadcrumbs, tabs, wizard steps, command palettes, form selection, table row actions, or bulk actions.",
|
|
5660
5665
|
"exampleTopics": [
|
|
5661
5666
|
"Basic Navigation",
|
|
5662
5667
|
"Navigation with heading",
|
|
@@ -5858,8 +5863,8 @@
|
|
|
5858
5863
|
"sourceRoot": "projects/components/notifications/src",
|
|
5859
5864
|
"docsPath": "/components/notifications",
|
|
5860
5865
|
"docsOverviewSource": "projects/docs/src/app/components/notifications/overview/overview.html",
|
|
5861
|
-
"purpose": "Display notification
|
|
5862
|
-
"useWhen": "Use for user
|
|
5866
|
+
"purpose": "Display user-facing notification events in a structured feed or inbox.",
|
|
5867
|
+
"useWhen": "Use Notifications for events addressed to the current user: comments, mentions, invitations, assignments, access requests, status changes, completed processes, and user-specific updates. Use ngs-notification for one event, ngsNotificationAvatar for the source avatar or icon, ngs-notification-message for the main sentence, ngs-notification-actor for the actor, ngs-notification-content for nested context such as a comment, file, quote, card, or preview, and ngs-notification-time for time. Use isUnread for unread state. Use ngs-notification-list with ngsNotificationDef when notifications come from an array and each type needs its own template. Use ngsNotificationControlsDef for per-notification controls such as mute, delete, or mark as read, often with Menu. Do not use Notifications for page-level system messages; use Alert or Announcement. Do not use for critical required actions; use ActionRequired. Do not use for service health; use Incidents. Do not use for generic activity feeds that are not user notifications; use List. Do not use for transient toast/snackbar messages.",
|
|
5863
5868
|
"exampleTopics": [
|
|
5864
5869
|
"Basic notifications",
|
|
5865
5870
|
"Notification list"
|
|
@@ -5951,8 +5956,8 @@
|
|
|
5951
5956
|
"sourceRoot": "projects/components/number-input/src",
|
|
5952
5957
|
"docsPath": "/forms/number-input",
|
|
5953
5958
|
"docsOverviewSource": "projects/docs/src/app/forms/number-input/overview/overview.html",
|
|
5954
|
-
"purpose": "Capture numeric
|
|
5955
|
-
"useWhen": "Use for quantities, limits,
|
|
5959
|
+
"purpose": "Capture a numeric form value with typing, stepper controls, min/max limits, and Angular forms integration.",
|
|
5960
|
+
"useWhen": "Use ngs-number-input inside one ngs-form-field when users need to type a number or adjust it with increase/decrease controls. Good for quantities, limits, thresholds, durations, percentages, ratings, numeric settings, seat counts, day counts, and budget-like numeric values. Use ngModel or formControlName, min and max for allowed bounds, step for increment/decrement size, readonly/disabled/required as normal form states, and ngsDecreaseControl or ngsIncreaseControl only when custom control icons are needed. Use TailwindCSS classes on ngs-form-field or surrounding layout for width and grouping. Do not use for normal text; use ngsInput. Do not use for phone numbers; use PhoneInput. Do not use for OTP, MFA, passcodes, or invite codes; use PinInput. Do not use for selecting currency; use CurrencySelect plus a numeric amount field when needed. Do not use for sliders/ranges, display-only KPI values, progress, or charts; use the dedicated component such as Gauge, ProgressBar, MicroChart, or a text/KPI layout.",
|
|
5956
5961
|
"exampleTopics": [
|
|
5957
5962
|
"Basic Number Input",
|
|
5958
5963
|
"Custom Controls",
|
|
@@ -6043,8 +6048,8 @@
|
|
|
6043
6048
|
"sourceRoot": "projects/components/option/src",
|
|
6044
6049
|
"docsPath": null,
|
|
6045
6050
|
"docsOverviewSource": null,
|
|
6046
|
-
"purpose": "Provide
|
|
6047
|
-
"useWhen": "Use
|
|
6051
|
+
"purpose": "Provide a low-level selectable option primitive for Select, Autocomplete, and other option-parent controls.",
|
|
6052
|
+
"useWhen": "Use ngs-option inside ngs-select, ngs-autocomplete, and other NgStarter dropdown/listbox controls that explicitly expect options, such as CountrySelect, CurrencySelect, DateFormatSelect, Timepicker, FilterBuilder, and similar controls. Use [value] for the form value and disabled when the option cannot be selected. Use ngs-optgroup to group related options under a label. Keep option text short and readable because the viewValue is derived from the rendered text. Do not use ngs-option as a generic list row, button, menu item, navigation item, table row, card, or custom layout block. Use MenuItem or Button for actions, Navigation/List/NavList for navigation and lists, RadioCard for rich card selection, and ColorSwitcher for fixed color choices. Agents usually should not import Option separately unless they are composing Select, Autocomplete, or another option-based component.",
|
|
6048
6053
|
"exampleTopics": [],
|
|
6049
6054
|
"minimalExample": null,
|
|
6050
6055
|
"exampleFiles": [],
|
|
@@ -1,11 +1,48 @@
|
|
|
1
|
+
const onlyDigits = (value) => {
|
|
2
|
+
return String(value ?? '').replace(/\D/g, '');
|
|
3
|
+
};
|
|
4
|
+
const isValidLuhn = (value) => {
|
|
5
|
+
let sum = 0;
|
|
6
|
+
let shouldDouble = false;
|
|
7
|
+
for (let i = value.length - 1; i >= 0; i--) {
|
|
8
|
+
let digit = Number(value[i]);
|
|
9
|
+
if (shouldDouble) {
|
|
10
|
+
digit *= 2;
|
|
11
|
+
if (digit > 9) {
|
|
12
|
+
digit -= 9;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
sum += digit;
|
|
16
|
+
shouldDouble = !shouldDouble;
|
|
17
|
+
}
|
|
18
|
+
return sum % 10 === 0;
|
|
19
|
+
};
|
|
20
|
+
function creditCardNumberValidator() {
|
|
21
|
+
return (control) => {
|
|
22
|
+
const value = onlyDigits(control.value);
|
|
23
|
+
if (!value) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
if (value.length < 12 || value.length > 19 || !isValidLuhn(value)) {
|
|
27
|
+
return { creditCardNumberInvalid: true };
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
1
32
|
function expiryDateValidator() {
|
|
2
33
|
return (control) => {
|
|
3
|
-
const value = control.value;
|
|
4
|
-
if (!value
|
|
34
|
+
const value = onlyDigits(control.value);
|
|
35
|
+
if (!value) {
|
|
5
36
|
return null;
|
|
6
37
|
}
|
|
38
|
+
if (value.length !== 4) {
|
|
39
|
+
return { expiryDateInvalid: true };
|
|
40
|
+
}
|
|
7
41
|
const month = parseInt(value.substring(0, 2), 10);
|
|
8
42
|
const year = parseInt(value.substring(2, 4), 10);
|
|
43
|
+
if (month < 1 || month > 12) {
|
|
44
|
+
return { expiryDateInvalid: true };
|
|
45
|
+
}
|
|
9
46
|
const currentDate = new Date();
|
|
10
47
|
const currentMonth = currentDate.getMonth() + 1;
|
|
11
48
|
const currentYear = parseInt(currentDate.getFullYear().toString().substring(2, 4));
|
|
@@ -15,10 +52,29 @@ function expiryDateValidator() {
|
|
|
15
52
|
return null;
|
|
16
53
|
};
|
|
17
54
|
}
|
|
55
|
+
function creditCardCvvValidator(options = {}) {
|
|
56
|
+
const minLength = options.minLength ?? 3;
|
|
57
|
+
const maxLength = options.maxLength ?? 4;
|
|
58
|
+
return (control) => {
|
|
59
|
+
const value = onlyDigits(control.value);
|
|
60
|
+
if (!value) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
if (value.length < minLength || value.length > maxLength) {
|
|
64
|
+
return {
|
|
65
|
+
creditCardCvvInvalid: {
|
|
66
|
+
minLength,
|
|
67
|
+
maxLength,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
18
74
|
|
|
19
75
|
/**
|
|
20
76
|
* Generated bundle index. Do not edit.
|
|
21
77
|
*/
|
|
22
78
|
|
|
23
|
-
export { expiryDateValidator };
|
|
79
|
+
export { creditCardCvvValidator, creditCardNumberValidator, expiryDateValidator };
|
|
24
80
|
//# sourceMappingURL=ngstarter-ui-components-input-validator.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngstarter-ui-components-input-validator.mjs","sources":["../../../projects/components/input-validator/src/expiry-date-validator.ts","../../../projects/components/input-validator/ngstarter-ui-components-input-validator.ts"],"sourcesContent":["import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';\n\nexport function
|
|
1
|
+
{"version":3,"file":"ngstarter-ui-components-input-validator.mjs","sources":["../../../projects/components/input-validator/src/expiry-date-validator.ts","../../../projects/components/input-validator/ngstarter-ui-components-input-validator.ts"],"sourcesContent":["import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';\n\nconst onlyDigits = (value: unknown): string => {\n return String(value ?? '').replace(/\\D/g, '');\n};\n\nconst isValidLuhn = (value: string): boolean => {\n let sum = 0;\n let shouldDouble = false;\n\n for (let i = value.length - 1; i >= 0; i--) {\n let digit = Number(value[i]);\n\n if (shouldDouble) {\n digit *= 2;\n if (digit > 9) {\n digit -= 9;\n }\n }\n\n sum += digit;\n shouldDouble = !shouldDouble;\n }\n\n return sum % 10 === 0;\n};\n\nexport function creditCardNumberValidator(): ValidatorFn {\n return (control: AbstractControl): ValidationErrors | null => {\n const value = onlyDigits(control.value);\n\n if (!value) {\n return null;\n }\n\n if (value.length < 12 || value.length > 19 || !isValidLuhn(value)) {\n return { creditCardNumberInvalid: true };\n }\n\n return null;\n };\n}\n\nexport function expiryDateValidator(): ValidatorFn {\n return (control: AbstractControl): ValidationErrors | null => {\n const value = onlyDigits(control.value);\n\n if (!value) {\n return null;\n }\n\n if (value.length !== 4) {\n return { expiryDateInvalid: true };\n }\n\n const month = parseInt(value.substring(0, 2), 10);\n const year = parseInt(value.substring(2, 4), 10);\n\n if (month < 1 || month > 12) {\n return { expiryDateInvalid: true };\n }\n\n const currentDate = new Date();\n const currentMonth = currentDate.getMonth() + 1;\n const currentYear = parseInt(currentDate.getFullYear().toString().substring(2, 4));\n\n if (year < currentYear || (year === currentYear && month < currentMonth)) {\n return { expiryDateInPast: true };\n }\n\n return null;\n };\n}\n\nexport interface CreditCardCvvValidatorOptions {\n minLength?: number;\n maxLength?: number;\n}\n\nexport function creditCardCvvValidator(options: CreditCardCvvValidatorOptions = {}): ValidatorFn {\n const minLength = options.minLength ?? 3;\n const maxLength = options.maxLength ?? 4;\n\n return (control: AbstractControl): ValidationErrors | null => {\n const value = onlyDigits(control.value);\n\n if (!value) {\n return null;\n }\n\n if (value.length < minLength || value.length > maxLength) {\n return {\n creditCardCvvInvalid: {\n minLength,\n maxLength,\n },\n };\n }\n\n return null;\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ngstarter-ui/components",
|
|
3
3
|
"description": "NgStarter - AI-friendly Enterprise Angular UI Components and Admin Panel",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.35",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/elementarlabsdev/ngstarter.git"
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { ValidatorFn } from '@angular/forms';
|
|
2
2
|
|
|
3
|
+
declare function creditCardNumberValidator(): ValidatorFn;
|
|
3
4
|
declare function expiryDateValidator(): ValidatorFn;
|
|
5
|
+
interface CreditCardCvvValidatorOptions {
|
|
6
|
+
minLength?: number;
|
|
7
|
+
maxLength?: number;
|
|
8
|
+
}
|
|
9
|
+
declare function creditCardCvvValidator(options?: CreditCardCvvValidatorOptions): ValidatorFn;
|
|
4
10
|
|
|
5
|
-
export { expiryDateValidator };
|
|
11
|
+
export { creditCardCvvValidator, creditCardNumberValidator, expiryDateValidator };
|
|
12
|
+
export type { CreditCardCvvValidatorOptions };
|