@nexub/core 0.0.0-stage → 2.2.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.
@@ -0,0 +1,138 @@
1
+ /** Every user-facing default string in @nexub/react and @nexub/react-native. Explicit component props still win. */
2
+ interface NexubMessages {
3
+ close: string;
4
+ dismissAlert: string;
5
+ dismissBanner: string;
6
+ remove: string;
7
+ removeFilter: string;
8
+ removeFile: (fileName: string) => string;
9
+ uploadFiles: string;
10
+ clickToUpload: string;
11
+ orDragAndDrop: string;
12
+ clearSearch: string;
13
+ showPassword: string;
14
+ hidePassword: string;
15
+ increment: string;
16
+ decrement: string;
17
+ loading: string;
18
+ pagination: string;
19
+ previousPage: string;
20
+ nextPage: string;
21
+ goToPage: (page: number) => string;
22
+ breadcrumb: string;
23
+ breadcrumbMore: string;
24
+ moreCount: (count: number) => string;
25
+ rating: string;
26
+ ratingStars: (stars: number) => string;
27
+ mainNavigation: string;
28
+ sidebar: string;
29
+ searchPlaceholder: string;
30
+ noResults: string;
31
+ pickDate: string;
32
+ pickDateRange: string;
33
+ /** Calendar nav and day labels (DatePicker, DateRangePicker). */
34
+ previousMonth: string;
35
+ nextMonth: string;
36
+ calendarNavigation: string;
37
+ /** Wraps a day's formatted date when it is today. */
38
+ todayDate: (date: string) => string;
39
+ /** Wraps a day's (possibly today-wrapped) label when it is selected. */
40
+ selectedDate: (label: string) => string;
41
+ commandPalette: string;
42
+ /** Toaster region label; Radix replaces `{hotkey}`. */
43
+ notifications: string;
44
+ undo: string;
45
+ promptLabel: string;
46
+ sendMessage: string;
47
+ stopGenerating: string;
48
+ promptHint: string;
49
+ thinking: string;
50
+ youSaid: string;
51
+ assistantSaid: string;
52
+ failedToSend: string;
53
+ retry: string;
54
+ copy: string;
55
+ copied: string;
56
+ goodResponse: string;
57
+ badResponse: string;
58
+ regenerate: string;
59
+ sources: string;
60
+ source: (index: number) => string;
61
+ jumpToLatest: string;
62
+ conversation: string;
63
+ pageOf: (page: number, total: number) => string;
64
+ previous: string;
65
+ next: string;
66
+ search: string;
67
+ searchProduct: (productName: string) => string;
68
+ keyboardShortcut: (shortcut: string) => string;
69
+ commandKey: string;
70
+ controlKey: string;
71
+ searching: string;
72
+ searchFailed: string;
73
+ noResultsFor: (query: string) => string;
74
+ typeToSearch: string;
75
+ switchOrganization: (name: string) => string;
76
+ organizations: string;
77
+ switchToLightTheme: string;
78
+ switchToDarkTheme: string;
79
+ glass: string;
80
+ glassClear: string;
81
+ glassBalanced: string;
82
+ glassTinted: string;
83
+ glassSolid: string;
84
+ accountMenu: (name: string) => string;
85
+ manageAccount: string;
86
+ privacyPolicy: string;
87
+ termsOfService: string;
88
+ signOut: string;
89
+ signingOut: string;
90
+ accountAndApps: string;
91
+ /** Sheet grabber: cycles the sheet height. */
92
+ resize: string;
93
+ cancel: string;
94
+ show: (label: string) => string;
95
+ hide: (label: string) => string;
96
+ /** Read in place of a masked value. */
97
+ hidden: string;
98
+ deleteDigit: string;
99
+ /** OTP / PIN entry, e.g. "Digit 2 of 6". */
100
+ codeDigit: (index: number, total: number) => string;
101
+ offline: string;
102
+ page: (index: number, total: number) => string;
103
+ moreActions: string;
104
+ }
105
+ declare const defaultMessages: NexubMessages;
106
+ type Direction = 'ltr' | 'rtl';
107
+ /** 'rtl' for Arabic, Hebrew, Persian and Urdu locales, else 'ltr'. */
108
+ declare function directionOf(locale: string): Direction;
109
+
110
+ declare function moneyFormatter(currency: string, locale?: string, options?: Intl.NumberFormatOptions): Intl.NumberFormat;
111
+ /** The currency's fraction digits for this locale (JPY 0, USD 2, KWD 3). */
112
+ declare function fractionDigits(currency: string, locale?: string): number;
113
+ /** The narrow symbol on its own, e.g. "$", "€", "₹". */
114
+ declare function currencySymbol(currency: string, locale?: string): string;
115
+ /** Plain number text for editing: locale decimal separator, no grouping, no symbol. */
116
+ declare function formatForEditing(value: number, currency: string, locale?: string): string;
117
+ /** Display text: grouping and the currency's full fraction digits, no symbol. */
118
+ declare function formatForDisplay(value: number, currency: string, locale?: string): string;
119
+ /**
120
+ * Parses what a person typed into a number, or null when empty/unparseable.
121
+ * The locale's grouping separators are dropped and its decimal separator marks
122
+ * the fraction (so in de-DE "1.234,5" is 1234.5). Rounds to the currency's
123
+ * fraction digits.
124
+ */
125
+ declare function parseMoney(text: string, currency: string, locale?: string): number | null;
126
+
127
+ /** Semantic or product tone: overrides a component's colour with a role. */
128
+ type ToneValue = 'neutral' | 'info' | 'success' | 'warning' | 'danger' | 'leap' | 'bookub' | 'payub' | 'founderub';
129
+ /** Nexub product brands; each remaps the tertiary role family. */
130
+ type Product = 'leap' | 'bookub' | 'payub' | 'founderub';
131
+ /** Glass intensity dial (user preference). 'off' makes every glass surface solid. */
132
+ type GlassMode = 'clear' | 'balanced' | 'tinted' | 'off';
133
+ /** Contrast level of the colour scheme. */
134
+ type ContrastLevel = 'standard' | 'medium' | 'high';
135
+ /** The control ladder (24 / 32 / 40 / 48 / 56). */
136
+ type ControlSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
137
+
138
+ export { type ContrastLevel, type ControlSize, type Direction, type GlassMode, type NexubMessages, type Product, type ToneValue, currencySymbol, defaultMessages, directionOf, formatForDisplay, formatForEditing, fractionDigits, moneyFormatter, parseMoney };
package/dist/index.js ADDED
@@ -0,0 +1,150 @@
1
+ // src/messages.ts
2
+ var defaultMessages = {
3
+ close: "Close",
4
+ dismissAlert: "Dismiss alert",
5
+ dismissBanner: "Dismiss banner",
6
+ remove: "Remove",
7
+ removeFilter: "Remove filter",
8
+ removeFile: (fileName) => `Remove ${fileName}`,
9
+ uploadFiles: "Upload files",
10
+ clickToUpload: "Click to upload",
11
+ orDragAndDrop: "or drag and drop",
12
+ clearSearch: "Clear search",
13
+ showPassword: "Show password",
14
+ hidePassword: "Hide password",
15
+ increment: "Increment",
16
+ decrement: "Decrement",
17
+ loading: "Loading\u2026",
18
+ pagination: "Pagination",
19
+ previousPage: "Go to previous page",
20
+ nextPage: "Go to next page",
21
+ goToPage: (page) => `Go to page ${page}`,
22
+ breadcrumb: "breadcrumb",
23
+ breadcrumbMore: "More",
24
+ moreCount: (count) => `${count} more`,
25
+ rating: "Rating",
26
+ ratingStars: (stars) => `${stars} star${stars !== 1 ? "s" : ""}`,
27
+ mainNavigation: "Main",
28
+ sidebar: "Sidebar",
29
+ searchPlaceholder: "Search\u2026",
30
+ noResults: "No results found.",
31
+ pickDate: "Pick a date",
32
+ pickDateRange: "Pick a date range",
33
+ previousMonth: "Go to previous month",
34
+ nextMonth: "Go to next month",
35
+ calendarNavigation: "Calendar navigation",
36
+ todayDate: (date) => `Today, ${date}`,
37
+ selectedDate: (label) => `${label}, selected`,
38
+ commandPalette: "Command palette",
39
+ notifications: "Notifications ({hotkey})",
40
+ undo: "Undo",
41
+ promptLabel: "Message",
42
+ sendMessage: "Send message",
43
+ stopGenerating: "Stop generating",
44
+ promptHint: "Press Enter to send, Shift+Enter for a new line",
45
+ thinking: "Thinking",
46
+ youSaid: "You said",
47
+ assistantSaid: "Assistant said",
48
+ failedToSend: "Failed to send",
49
+ retry: "Retry",
50
+ copy: "Copy",
51
+ copied: "Copied",
52
+ goodResponse: "Good response",
53
+ badResponse: "Bad response",
54
+ regenerate: "Regenerate",
55
+ sources: "Sources",
56
+ source: (n) => `Source ${n}`,
57
+ jumpToLatest: "Jump to latest",
58
+ conversation: "Conversation",
59
+ pageOf: (page, total) => `Page ${page} of ${total}`,
60
+ previous: "Previous",
61
+ next: "Next",
62
+ search: "Search",
63
+ searchProduct: (productName) => `Search ${productName}`,
64
+ keyboardShortcut: (shortcut) => `Keyboard shortcut: ${shortcut}`,
65
+ commandKey: "Command",
66
+ controlKey: "Control",
67
+ searching: "Searching\u2026",
68
+ searchFailed: "Search failed. Try again.",
69
+ noResultsFor: (query) => `No results for \u201C${query}\u201D`,
70
+ typeToSearch: "Type to search",
71
+ switchOrganization: (name) => `${name}, switch organization`,
72
+ organizations: "Organizations",
73
+ switchToLightTheme: "Switch to light theme",
74
+ switchToDarkTheme: "Switch to dark theme",
75
+ glass: "Glass",
76
+ glassClear: "Clear",
77
+ glassBalanced: "Balanced",
78
+ glassTinted: "Tinted",
79
+ glassSolid: "Solid",
80
+ accountMenu: (name) => `Account: ${name}`,
81
+ manageAccount: "Manage your Nexub Account",
82
+ privacyPolicy: "Privacy policy",
83
+ termsOfService: "Terms of service",
84
+ signOut: "Sign out",
85
+ signingOut: "Signing out\u2026",
86
+ accountAndApps: "Account and apps",
87
+ resize: "Resize",
88
+ cancel: "Cancel",
89
+ show: (label) => `Show ${label}`,
90
+ hide: (label) => `Hide ${label}`,
91
+ hidden: "Hidden",
92
+ deleteDigit: "Delete",
93
+ codeDigit: (index, total) => `Digit ${index} of ${total}`,
94
+ offline: "You\u2019re offline. Some things may not be up to date.",
95
+ page: (index, total) => `Page ${index} of ${total}`,
96
+ moreActions: "More actions"
97
+ };
98
+ var RTL_LANGUAGES = /* @__PURE__ */ new Set(["ar", "he", "fa", "ur"]);
99
+ function directionOf(locale) {
100
+ return RTL_LANGUAGES.has(locale.toLowerCase().split(/[-_]/)[0]) ? "rtl" : "ltr";
101
+ }
102
+
103
+ // src/money.ts
104
+ function part(fmt, n, type) {
105
+ if (typeof fmt.formatToParts === "function") return fmt.formatToParts(n).find((p) => p.type === type)?.value;
106
+ return /\p{Nd}([^\p{Nd}]+)\p{Nd}/u.exec(fmt.format(n))?.[1];
107
+ }
108
+ function moneyFormatter(currency, locale, options = {}) {
109
+ return new Intl.NumberFormat(locale, { style: "currency", currency, currencyDisplay: "narrowSymbol", ...options });
110
+ }
111
+ function fractionDigits(currency, locale) {
112
+ const fmt = moneyFormatter(currency, locale);
113
+ if (typeof fmt.resolvedOptions === "function") return fmt.resolvedOptions().maximumFractionDigits ?? 2;
114
+ const runs = fmt.format(0).match(/\p{Nd}+/gu) ?? [];
115
+ return runs.length > 1 ? runs[runs.length - 1].length : 0;
116
+ }
117
+ function currencySymbol(currency, locale) {
118
+ const fmt = moneyFormatter(currency, locale);
119
+ if (typeof fmt.formatToParts === "function")
120
+ return fmt.formatToParts(0).find((p) => p.type === "currency")?.value ?? currency;
121
+ const symbol = fmt.format(0).replace(/[\p{Nd}\s.,\u00a0\u202f\u066b\u066c'’-]/gu, "");
122
+ return symbol || currency;
123
+ }
124
+ function formatForEditing(value, currency, locale) {
125
+ return new Intl.NumberFormat(locale, {
126
+ useGrouping: false,
127
+ maximumFractionDigits: fractionDigits(currency, locale)
128
+ }).format(value);
129
+ }
130
+ function formatForDisplay(value, currency, locale) {
131
+ const digits = fractionDigits(currency, locale);
132
+ return new Intl.NumberFormat(locale, { minimumFractionDigits: digits, maximumFractionDigits: digits }).format(value);
133
+ }
134
+ function parseMoney(text, currency, locale) {
135
+ const plain = new Intl.NumberFormat(locale);
136
+ const decimal = part(plain, 1.1, "decimal") ?? ".";
137
+ const group = part(plain, 1e4, "group");
138
+ let s = text.trim().replace(/[\s\u00a0\u202f]/g, "");
139
+ if (group && group !== decimal) s = s.split(group).join("");
140
+ s = s.replace(decimal, ".").replace(/[−–]/g, "-").replace(/[^0-9.-]/g, "");
141
+ const negative = s.startsWith("-");
142
+ s = s.replace(/-/g, "");
143
+ if (!/\d/.test(s) || (s.match(/\./g) ?? []).length > 1) return null;
144
+ const n = Number(s);
145
+ if (!Number.isFinite(n)) return null;
146
+ const f = 10 ** fractionDigits(currency, locale);
147
+ return (negative ? -1 : 1) * (Math.round(n * f) / f);
148
+ }
149
+
150
+ export { currencySymbol, defaultMessages, directionOf, formatForDisplay, formatForEditing, fractionDigits, moneyFormatter, parseMoney };
package/package.json CHANGED
@@ -1,6 +1,46 @@
1
1
  {
2
2
  "name": "@nexub/core",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "2.2.0",
4
+ "description": "Platform-neutral core of Nexub Design System, shared by @nexub/react (web) and @nexub/react-native: UI strings, locale direction, money formatting and shared prop types. Pure TypeScript, no DOM, no React.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "homepage": "https://github.com/Nexub-AI/nexub-ds#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/Nexub-AI/nexub-ds.git",
11
+ "directory": "packages/core"
12
+ },
13
+ "keywords": [
14
+ "design-system",
15
+ "i18n",
16
+ "money",
17
+ "nexub"
18
+ ],
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "files": [
23
+ "dist"
24
+ ],
25
+ "sideEffects": false,
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.ts",
29
+ "default": "./dist/index.js"
30
+ },
31
+ "./package.json": "./package.json"
32
+ },
33
+ "main": "./dist/index.js",
34
+ "types": "./dist/index.d.ts",
35
+ "devDependencies": {
36
+ "tsup": "^8.5.1",
37
+ "typescript": "^5.9.3"
38
+ },
39
+ "scripts": {
40
+ "build": "tsup",
41
+ "dev": "tsup --watch",
42
+ "clean": "rm -rf dist",
43
+ "typecheck": "tsc --noEmit",
44
+ "lint": "eslint src"
45
+ }
6
46
  }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.