@samline/date 2.1.1 → 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.
package/README.md CHANGED
@@ -11,6 +11,7 @@ Day.js repository: https://github.com/iamkun/dayjs
11
11
  - format dates with configurable input and output patterns
12
12
  - default locale is English
13
13
  - load and switch supported locales on demand
14
+ - manipulate and compare dates through a chainable helper
14
15
  - create formatter instances with isolated locale state
15
16
  - enable strict parsing globally per formatter or per call
16
17
  - parse and validate dates with explicit result objects
@@ -19,7 +20,7 @@ Day.js repository: https://github.com/iamkun/dayjs
19
20
  ## Table of Contents
20
21
 
21
22
  - [Installation](#installation)
22
- - [Browser and CDN](#browser-and-cdn)
23
+ - [CDN / Browser](#cdn--browser)
23
24
  - [Entrypoints](#entrypoints)
24
25
  - [Quick Start](#quick-start)
25
26
  - [API](#api)
@@ -47,49 +48,46 @@ yarn add @samline/date
47
48
  bun add @samline/date
48
49
  ```
49
50
 
50
- ## Browser and CDN
51
+ ## CDN / Browser
51
52
 
52
- If your project does not use a bundler, load the browser build from a CDN. Prefer pinning a version instead of using `latest` in production.
53
+ Use the browser bundle when your project loads scripts directly in the page and cannot compile npm modules.
53
54
 
54
- ```html
55
- <script type="module">
56
- import { DateKit } from 'https://cdn.jsdelivr.net/npm/@samline/date@2.1.1/dist/browser/global.js'
57
-
58
- const value = await DateKit.getDate({
59
- date: '23/03/2026',
60
- input: 'DD/MM/YYYY',
61
- output: 'MMMM D, YYYY'
62
- })
55
+ This is useful in environments such as Shopify themes, WordPress templates, or plain HTML pages with no build step.
63
56
 
64
- console.log(value)
65
- console.log(window.DateKit.resolveLocale('en-us'))
66
- </script>
57
+ ```html
58
+ <script src="https://cdn.jsdelivr.net/npm/@samline/date@2.2.0/dist/browser/date.global.js"></script>
67
59
  ```
68
60
 
69
- You can also use unpkg:
61
+ Then use it from a normal script:
70
62
 
71
63
  ```html
72
- <script type="module">
73
- import { DateKit } from 'https://unpkg.com/@samline/date@2.1.1/dist/browser/global.js'
74
-
75
- console.log(await DateKit.isValidDate({
76
- date: '23/03/2026',
77
- input: 'DD/MM/YYYY'
78
- }))
64
+ <script>
65
+ ;(async () => {
66
+ const value = await window.DateKit.getDate({
67
+ date: '23/03/2026',
68
+ input: 'DD/MM/YYYY',
69
+ output: 'MMMM D, YYYY'
70
+ })
71
+
72
+ console.log(value)
73
+ console.log(window.DateKit.resolveLocale('en-us'))
74
+ })()
79
75
  </script>
80
76
  ```
81
77
 
82
- The browser bundle exposes `window.DateKit` and the same shared helpers documented below.
78
+ After the CDN script loads, the browser build exposes `window.DateKit`.
79
+
80
+ Use one of the package manager commands above when your project has a build step. If you are working in Shopify, WordPress, or any browser-only template without compilation, use the browser bundle described in [docs/browser.md](docs/browser.md).
83
81
 
84
82
  ## Entrypoints
85
83
 
86
84
  | Entrypoint | Main API | Purpose |
87
85
  | --- | --- | --- |
88
- | `@samline/date` | `createDateFormatter`, `getDate`, `parseDate`, `isValidDate` | shared core API |
86
+ | `@samline/date` | `createDateChain`, `createDateFormatter`, `getDate`, `parseDate`, `isValidDate` | shared core API |
89
87
  | `@samline/date/vanilla` | same exports as root | utility wrapper for plain TypeScript or JavaScript |
90
- | `@samline/date/react` | `useDateFormatter` | React hook with scoped formatter state |
91
- | `@samline/date/vue` | `useDateFormatter` | Vue composable with reactive locale state |
92
- | `@samline/date/svelte` | `createDateFormatterStore` | Svelte store-driven formatter API |
88
+ | `@samline/date/react` | `useDateFormatter` | React hook with scoped formatter and chain state |
89
+ | `@samline/date/vue` | `useDateFormatter` | Vue composable with reactive formatter and chain state |
90
+ | `@samline/date/svelte` | `createDateFormatterStore` | Svelte store-driven formatter and chain API |
93
91
  | `@samline/date/browser` | `DateKit` | browser global build for projects without a bundler |
94
92
 
95
93
  ## Quick Start
@@ -144,6 +142,7 @@ resolveLocale('zz-zz')
144
142
 
145
143
  The shared root entrypoint exports:
146
144
 
145
+ - `createDateChain(props?, config?)`
147
146
  - `createDateFormatter(config?)`
148
147
  - `getDate(props?, config?)`
149
148
  - `parseDate(props, config?)`
@@ -161,6 +160,7 @@ createDateFormatter(config?: {
161
160
  strict?: boolean
162
161
  invalid?: string
163
162
  }): {
163
+ createDateChain(props?: CreateDateChainOptions): DateChain
164
164
  getDate(props?: GetDateOptions): string
165
165
  parseDate(props: DateParsingOptions): ParseDateResult
166
166
  isValidDate(props: DateParsingOptions): boolean
@@ -181,6 +181,7 @@ Regional locale input falls back to the base locale when the exact variant is no
181
181
 
182
182
  The formatter instance exposes:
183
183
 
184
+ - `createDateChain(props?)`
184
185
  - `getDate(props?)`
185
186
  - `parseDate(props)`
186
187
  - `isValidDate(props)`
@@ -209,6 +210,7 @@ These helpers are also available in the browser build through `DateKit.getSuppor
209
210
  ### One-shot helpers
210
211
 
211
212
  ```ts
213
+ createDateChain(props?: CreateDateChainOptions, config?: DateFormatterConfig): DateChain
212
214
  getDate(props?: GetDateOptions, config?: DateFormatterConfig): Promise<string>
213
215
  parseDate(props: DateParsingOptions, config?: DateFormatterConfig): Promise<ParseDateResult>
214
216
  isValidDate(props: DateParsingOptions, config?: DateFormatterConfig): Promise<boolean>
@@ -220,12 +222,25 @@ All three helpers are async because they can load locale data before running the
220
222
 
221
223
  | Helper | Returns | Use it when you need |
222
224
  | --- | --- | --- |
225
+ | `createDateChain(...)` | chainable date helper | a one-shot manipulation or comparison flow with multiple date operations |
223
226
  | `getDate(...)` | formatted string | a final display value |
224
227
  | `parseDate(...)` | structured parse result | validation details, `Date`, `iso`, `timestamp`, or deferred formatting |
225
228
  | `isValidDate(...)` | boolean | only a yes or no validation check |
226
229
 
227
230
  ```ts
228
- import { getDate, isValidDate, parseDate } from '@samline/date'
231
+ import { createDateChain, getDate, isValidDate, parseDate } from '@samline/date'
232
+
233
+ const chain = createDateChain({
234
+ date: '23/03/2026',
235
+ input: 'DD/MM/YYYY'
236
+ })
237
+
238
+ await chain.ready
239
+
240
+ const moved = chain
241
+ .add(3, 'month')
242
+ .set('day', 1)
243
+ .format('YYYY-MM-DD')
229
244
 
230
245
  const value = await getDate({
231
246
  date: '23/03/2026',
@@ -244,10 +259,76 @@ const valid = await isValidDate({
244
259
  })
245
260
  ```
246
261
 
247
- They load the requested locale automatically and also use `strict: true` by default.
262
+ `getDate`, `parseDate`, and `isValidDate` are async because they can load locale data before running the operation.
263
+
264
+ `createDateChain` is also a valid one-shot helper. It returns immediately, but you must `await chain.ready` before using it when the locale may need to load.
265
+
266
+ All of these helpers use `strict: true` by default.
248
267
 
249
268
  If you call `getDate()` without props, it returns the current date formatted with the default formatter settings.
250
269
 
270
+ ### createDateChain
271
+
272
+ ```ts
273
+ const chain = createDateChain({
274
+ date: '23/03/2026',
275
+ input: 'DD/MM/YYYY',
276
+ locale: 'es',
277
+ strict: true,
278
+ invalid: 'Fecha invalida'
279
+ })
280
+
281
+ await chain.ready
282
+
283
+ chain
284
+ .add(3, 'month')
285
+ .set('day', 1)
286
+ .format('YYYY-MM-DD')
287
+ ```
288
+
289
+ Use this helper when you want to parse a date and then manipulate or compare it in the same flow.
290
+
291
+ The chainable helper exposes:
292
+
293
+ - `add(value, unit)`
294
+ - `subtract(value, unit)`
295
+ - `set(unit, value)`
296
+ - `startOf(unit)`
297
+ - `endOf(unit)`
298
+ - `format(output?)`
299
+ - `toDate()`
300
+ - `toISOString()`
301
+ - `toTimestamp()`
302
+ - `isValid()`
303
+ - `isBefore(other, unit?)`
304
+ - `isAfter(other, unit?)`
305
+ - `isSame(other, unit?)`
306
+ - `toState()`
307
+ - `ready`
308
+
309
+ `set('day', value)` is the public way to change the day of the month. Internally it maps to Day.js `set('date', value)` so the behavior stays aligned with Day.js while the public API stays clearer.
310
+
311
+ `toState()` returns the current structured state of the chain:
312
+
313
+ - valid state: `isValid`, `locale`, `date`, `iso`, `timestamp`
314
+ - invalid state: `isValid`, `locale`, `date: null`, `iso: null`, `timestamp: null`, `error`
315
+
316
+ Example:
317
+
318
+ ```ts
319
+ const chain = createDateChain({
320
+ date: '23/03/2026',
321
+ input: 'DD/MM/YYYY'
322
+ })
323
+
324
+ await chain.ready
325
+
326
+ const finalState = chain
327
+ .add(3, 'month')
328
+ .endOf('month')
329
+ .toState()
330
+ ```
331
+
251
332
  ### parseDate
252
333
 
253
334
  ```ts