@jjlmoya/utils-nature 1.26.0 → 1.28.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.
Files changed (38) hide show
  1. package/package.json +1 -1
  2. package/src/entries.ts +4 -1
  3. package/src/index.ts +2 -0
  4. package/src/tests/tool_validation.test.ts +2 -2
  5. package/src/tool/seedStratificationCalendar/bibliography.astro +9 -0
  6. package/src/tool/seedStratificationCalendar/bibliography.ts +16 -0
  7. package/src/tool/seedStratificationCalendar/calendar-actions.ts +66 -0
  8. package/src/tool/seedStratificationCalendar/component.astro +62 -0
  9. package/src/tool/seedStratificationCalendar/controller.ts +227 -0
  10. package/src/tool/seedStratificationCalendar/dom-views.ts +130 -0
  11. package/src/tool/seedStratificationCalendar/entry.ts +29 -0
  12. package/src/tool/seedStratificationCalendar/evaluator.ts +32 -0
  13. package/src/tool/seedStratificationCalendar/i18n/de.ts +35 -0
  14. package/src/tool/seedStratificationCalendar/i18n/en.ts +149 -0
  15. package/src/tool/seedStratificationCalendar/i18n/es.ts +35 -0
  16. package/src/tool/seedStratificationCalendar/i18n/fr.ts +35 -0
  17. package/src/tool/seedStratificationCalendar/i18n/id.ts +35 -0
  18. package/src/tool/seedStratificationCalendar/i18n/it.ts +35 -0
  19. package/src/tool/seedStratificationCalendar/i18n/ja.ts +35 -0
  20. package/src/tool/seedStratificationCalendar/i18n/ko.ts +35 -0
  21. package/src/tool/seedStratificationCalendar/i18n/nl.ts +35 -0
  22. package/src/tool/seedStratificationCalendar/i18n/pl.ts +35 -0
  23. package/src/tool/seedStratificationCalendar/i18n/pt.ts +35 -0
  24. package/src/tool/seedStratificationCalendar/i18n/ru.ts +35 -0
  25. package/src/tool/seedStratificationCalendar/i18n/sv.ts +35 -0
  26. package/src/tool/seedStratificationCalendar/i18n/tr.ts +35 -0
  27. package/src/tool/seedStratificationCalendar/i18n/zh.ts +35 -0
  28. package/src/tool/seedStratificationCalendar/index.ts +11 -0
  29. package/src/tool/seedStratificationCalendar/localized.ts +70 -0
  30. package/src/tool/seedStratificationCalendar/logic.test.ts +53 -0
  31. package/src/tool/seedStratificationCalendar/logic.ts +198 -0
  32. package/src/tool/seedStratificationCalendar/profile-labels.ts +18 -0
  33. package/src/tool/seedStratificationCalendar/profile-select.ts +43 -0
  34. package/src/tool/seedStratificationCalendar/seed-stratification-calendar.css +558 -0
  35. package/src/tool/seedStratificationCalendar/seo.astro +10 -0
  36. package/src/tool/seedStratificationCalendar/storage.ts +27 -0
  37. package/src/tool/seedStratificationCalendar/ui.ts +66 -0
  38. package/src/tools.ts +3 -1
@@ -0,0 +1,43 @@
1
+ import type { SeedStratificationCalendarUI } from './ui';
2
+ import { profileLabels } from './profile-labels';
3
+
4
+ export interface SelectParts {
5
+ root: HTMLElement;
6
+ trigger: HTMLButtonElement;
7
+ menu: HTMLElement;
8
+ choose: (id: string) => void;
9
+ }
10
+
11
+ function query<T extends Element>(root: HTMLElement, selector: string): T {
12
+ const element = root.querySelector<T>(selector);
13
+ if (!element) throw new Error(`Missing calendar element ${selector}`);
14
+ return element;
15
+ }
16
+
17
+ export function setupSelect(root: HTMLElement, ui: SeedStratificationCalendarUI, initialId: string, onSelect: (id: string) => void): SelectParts {
18
+ const select = query<HTMLElement>(root, '[data-role="profile-select"]');
19
+ const trigger = query<HTMLButtonElement>(select, '[data-select-trigger]');
20
+ const menu = query<HTMLElement>(select, '[data-select-menu]');
21
+ const labels = profileLabels(ui);
22
+ const choose = (id: string): void => {
23
+ select.dataset.value = id;
24
+ trigger.replaceChildren(document.createTextNode(labels[id] ?? labels.apple ?? ''));
25
+ const chevron = document.createElement('span');
26
+ chevron.className = 'n-chevron';
27
+ chevron.setAttribute('aria-hidden', 'true');
28
+ trigger.append(chevron);
29
+ menu.hidden = true;
30
+ trigger.setAttribute('aria-expanded', 'false');
31
+ menu.querySelectorAll<HTMLButtonElement>('[data-option]').forEach((option) => {
32
+ const isActive = option.dataset.option === id;
33
+ option.classList.toggle('is-active', isActive);
34
+ option.setAttribute('aria-selected', String(isActive));
35
+ });
36
+ onSelect(id);
37
+ };
38
+ menu.querySelectorAll<HTMLButtonElement>('[data-option]').forEach((option) => option.addEventListener('click', () => choose(option.dataset.option ?? initialId)));
39
+ trigger.addEventListener('click', () => { menu.hidden = !menu.hidden; trigger.setAttribute('aria-expanded', String(!menu.hidden)); });
40
+ document.addEventListener('click', (event) => { if (!select.contains(event.target as Node)) menu.hidden = true; });
41
+ choose(initialId);
42
+ return { root: select, trigger, menu, choose };
43
+ }
@@ -0,0 +1,558 @@
1
+ .n-seed-calendar {
2
+ --n-ink: #25352d;
3
+ --n-muted: #607166;
4
+ --n-paper: #f5f0e6;
5
+ --n-card: #fffdf7;
6
+ --n-line: #d8d1c2;
7
+ --n-moss: #426c4b;
8
+ --n-moss-soft: #dfeadd;
9
+ --n-amber: #b56d29;
10
+ --n-coral: #b65043;
11
+ --n-shadow: rgba(49, 58, 44, 0.12);
12
+
13
+ display: grid;
14
+ grid-template-columns: minmax(280px, 0.8fr) minmax(340px, 1.2fr);
15
+ overflow: hidden;
16
+ color: var(--n-ink);
17
+ background: var(--n-card);
18
+ border: 1px solid var(--n-line);
19
+ border-radius: 22px;
20
+ box-shadow: 0 18px 42px var(--n-shadow);
21
+ }
22
+ .theme-dark .n-seed-calendar {
23
+ --n-ink: #f3eee1;
24
+ --n-muted: #b9c7bb;
25
+ --n-paper: #1f2924;
26
+ --n-card: #29342e;
27
+ --n-line: #536258;
28
+ --n-moss: #a4ce9d;
29
+ --n-moss-soft: #384c3d;
30
+ --n-amber: #e6a35e;
31
+ --n-coral: #eb8b78;
32
+ --n-shadow: rgba(0, 0, 0, 0.3);
33
+ }
34
+ .n-calendar-controls {
35
+ display: flex;
36
+ flex-direction: column;
37
+ gap: 18px;
38
+ padding: clamp(22px, 4vw, 38px);
39
+ background: var(--n-paper);
40
+ }
41
+ .n-unit-switch {
42
+ display: grid;
43
+ gap: 8px;
44
+ }
45
+ .n-unit-options {
46
+ display: grid;
47
+ grid-template-columns: 1fr 1fr;
48
+ padding: 3px;
49
+ background: var(--n-card);
50
+ border: 1px solid var(--n-line);
51
+ border-radius: 10px;
52
+ }
53
+ .n-unit-button {
54
+ min-height: 36px;
55
+ color: var(--n-muted);
56
+ background: transparent;
57
+ border: 0;
58
+ border-radius: 7px;
59
+ font: inherit;
60
+ font-size: 0.8rem;
61
+ font-weight: 750;
62
+ cursor: pointer;
63
+ }
64
+ .n-unit-button.is-active {
65
+ color: var(--n-ink);
66
+ background: var(--n-moss-soft);
67
+ }
68
+
69
+ .n-mode-switch {
70
+ display: grid;
71
+ gap: 8px;
72
+ }
73
+
74
+ .n-mode-options {
75
+ display: grid;
76
+ grid-template-columns: 1fr 1fr;
77
+ gap: 4px;
78
+ }
79
+
80
+ .n-mode-button {
81
+ min-height: 40px;
82
+ padding: 0 10px;
83
+ color: var(--n-muted);
84
+ background: transparent;
85
+ border: 1px solid var(--n-line);
86
+ border-radius: 9px;
87
+ font: inherit;
88
+ font-size: 0.78rem;
89
+ font-weight: 700;
90
+ cursor: pointer;
91
+ }
92
+
93
+ .n-mode-button.is-active {
94
+ color: var(--n-ink);
95
+ background: var(--n-moss-soft);
96
+ border-color: var(--n-moss);
97
+ }
98
+ .n-control-block {
99
+ display: grid;
100
+ gap: 8px;
101
+ }
102
+ .n-field-label {
103
+ color: var(--n-muted);
104
+ font-size: 0.74rem;
105
+ font-weight: 750;
106
+ letter-spacing: 0.08em;
107
+ text-transform: uppercase;
108
+ }
109
+ .n-field, .n-select-trigger {
110
+ width: 100%;
111
+ min-height: 46px;
112
+ box-sizing: border-box;
113
+ padding: 0 14px;
114
+ color: var(--n-ink);
115
+ background: var(--n-card);
116
+ border: 1px solid var(--n-line);
117
+ border-radius: 10px;
118
+ font: inherit;
119
+ }
120
+ .n-field:focus, .n-select-trigger:focus, .n-range:focus {
121
+ outline: 3px solid var(--n-moss-soft);
122
+ outline-offset: 2px;
123
+ border-color: var(--n-moss);
124
+ }
125
+ .n-custom-select {
126
+ position: relative;
127
+ }
128
+ .n-select-trigger {
129
+ display: flex;
130
+ align-items: center;
131
+ justify-content: space-between;
132
+ cursor: pointer;
133
+ text-align: left;
134
+ }
135
+ .n-chevron {
136
+ width: 8px;
137
+ height: 8px;
138
+ border-right: 2px solid currentcolor;
139
+ border-bottom: 2px solid currentcolor;
140
+ transform: rotate(45deg) translateY(-2px);
141
+ }
142
+ .n-select-menu {
143
+ position: absolute;
144
+ z-index: 2;
145
+ top: calc(100% + 6px);
146
+ right: 0;
147
+ left: 0;
148
+ padding: 5px;
149
+ background: var(--n-card);
150
+ border: 1px solid var(--n-line);
151
+ border-radius: 12px;
152
+ box-shadow: 0 15px 30px var(--n-shadow);
153
+ }
154
+ .n-select-menu[hidden] {
155
+ display: none;
156
+ }
157
+ .n-select-option {
158
+ display: block;
159
+ width: 100%;
160
+ padding: 10px;
161
+ color: var(--n-ink);
162
+ background: transparent;
163
+ border: 0;
164
+ border-radius: 7px;
165
+ font: inherit;
166
+ text-align: left;
167
+ cursor: pointer;
168
+ }
169
+ .n-select-option:hover, .n-select-option.is-active {
170
+ background: var(--n-moss-soft);
171
+ }
172
+
173
+ .n-duration-grid {
174
+ display: grid;
175
+ grid-template-columns: repeat(3, 1fr);
176
+ gap: 10px;
177
+ }
178
+ .n-range-block {
179
+ display: grid;
180
+ gap: 10px;
181
+ padding-top: 4px;
182
+ }
183
+ .n-range-heading, .n-range-values, .n-control-actions, .n-calendar-header, .n-phase-date {
184
+ display: flex;
185
+ align-items: center;
186
+ justify-content: space-between;
187
+ gap: 10px;
188
+ }
189
+ .n-range-values {
190
+ color: var(--n-moss);
191
+ font-size: 0.85rem;
192
+ font-weight: 700;
193
+ }
194
+ .n-range-pair {
195
+ display: grid;
196
+ gap: 4px;
197
+ }
198
+ .n-range {
199
+ width: 100%;
200
+ accent-color: var(--n-moss);
201
+ }
202
+ .n-edit-hint {
203
+ margin: -3px 0 0;
204
+ color: var(--n-muted);
205
+ font-size: 0.82rem;
206
+ line-height: 1.45;
207
+ }
208
+ .n-primary-button, .n-quiet-button {
209
+ min-height: 44px;
210
+ padding: 0 16px;
211
+ border-radius: 9px;
212
+ font: inherit;
213
+ font-weight: 750;
214
+ cursor: pointer;
215
+ }
216
+ .n-primary-button {
217
+ flex: 1;
218
+ color: #fff;
219
+ background: var(--n-moss);
220
+ border: 1px solid var(--n-moss);
221
+ }
222
+ .n-quiet-button {
223
+ color: var(--n-ink);
224
+ background: transparent;
225
+ border: 1px solid var(--n-line);
226
+ }
227
+ .n-error {
228
+ margin: 0;
229
+ color: var(--n-coral);
230
+ font-size: 0.85rem;
231
+ }
232
+ .n-calendar-results {
233
+ padding: clamp(22px, 4vw, 38px);
234
+ overflow-x: auto;
235
+ }
236
+
237
+ .n-empty-state {
238
+ margin: 0;
239
+ color: var(--n-muted);
240
+ font-size: 0.95rem;
241
+ line-height: 1.5;
242
+ }
243
+
244
+ .n-gantt-heading {
245
+ margin: 0 0 12px;
246
+ font-size: 0.78rem;
247
+ letter-spacing: 0.08em;
248
+ text-transform: uppercase;
249
+ }
250
+
251
+ .n-gantt {
252
+ display: flex;
253
+ min-width: 640px;
254
+ min-height: 154px;
255
+ overflow: hidden;
256
+ border: 1px solid var(--n-line);
257
+ border-radius: 14px;
258
+ }
259
+
260
+ .n-gantt-segment {
261
+ display: flex;
262
+ min-width: 72px;
263
+ flex-direction: column;
264
+ gap: 7px;
265
+ padding: 14px;
266
+ color: var(--n-ink);
267
+ border-right: 1px solid var(--n-card);
268
+ }
269
+
270
+ .n-gantt-segment:last-child {
271
+ border-right: 0;
272
+ }
273
+
274
+ .n-gantt-segment svg {
275
+ width: 22px;
276
+ height: 22px;
277
+ }
278
+
279
+ .n-gantt-text {
280
+ display: grid;
281
+ gap: 2px;
282
+ }
283
+
284
+ .n-gantt-text strong {
285
+ font-size: 0.82rem;
286
+ }
287
+
288
+ .n-gantt-text span {
289
+ font-size: 0.7rem;
290
+ opacity: 0.78;
291
+ }
292
+
293
+ .n-gantt-segment .n-phase-detail {
294
+ margin-top: auto;
295
+ color: inherit;
296
+ font-size: 0.7rem;
297
+ line-height: 1.35;
298
+ }
299
+
300
+ .n-gantt-soak, .n-gantt-warm {
301
+ background: #f2d19b;
302
+ }
303
+
304
+ .n-gantt-cold {
305
+ background: #b9d5e7;
306
+ }
307
+
308
+ .n-gantt-sow {
309
+ background: #b9d6a8;
310
+ }
311
+
312
+ .theme-dark .n-gantt-soak, .theme-dark .n-gantt-warm {
313
+ color: #2c2418;
314
+ background: #d6a65e;
315
+ }
316
+
317
+ .theme-dark .n-gantt-cold {
318
+ color: #17262e;
319
+ background: #83b3cc;
320
+ }
321
+
322
+ .theme-dark .n-gantt-sow {
323
+ color: #1d2b1d;
324
+ background: #8fbf7e;
325
+ }
326
+
327
+ .n-gantt-segment.is-active {
328
+ outline: 3px solid var(--n-ink);
329
+ outline-offset: -3px;
330
+ }
331
+
332
+ .n-calendar-actions {
333
+ display: flex;
334
+ grid-column: 1 / -1;
335
+ align-items: center;
336
+ gap: 10px;
337
+ padding: 0 clamp(22px, 4vw, 38px) 22px;
338
+ }
339
+
340
+ .n-secondary-button {
341
+ min-height: 38px;
342
+ padding: 0 12px;
343
+ color: var(--n-ink);
344
+ background: transparent;
345
+ border: 1px solid var(--n-line);
346
+ border-radius: 8px;
347
+ font: inherit;
348
+ font-size: 0.75rem;
349
+ font-weight: 700;
350
+ cursor: pointer;
351
+ }
352
+
353
+ .n-secondary-button:hover, .n-secondary-button:focus-visible {
354
+ background: var(--n-moss-soft);
355
+ }
356
+
357
+ .n-share-status {
358
+ color: var(--n-moss);
359
+ font-size: 0.75rem;
360
+ font-weight: 700;
361
+ }
362
+
363
+ .n-print-label {
364
+ display: none;
365
+ }
366
+ .n-calendar-header {
367
+ padding-bottom: 18px;
368
+ border-bottom: 1px solid var(--n-line);
369
+ }
370
+ .n-status {
371
+ padding: 6px 9px;
372
+ border-radius: 999px;
373
+ font-size: 0.7rem;
374
+ font-weight: 800;
375
+ letter-spacing: 0.06em;
376
+ }
377
+ .n-status-upcoming {
378
+ color: var(--n-amber);
379
+ background: color-mix(in srgb, var(--n-amber) 16%, transparent);
380
+ }
381
+ .n-status-active, .n-status-sowing {
382
+ color: var(--n-moss);
383
+ background: var(--n-moss-soft);
384
+ }
385
+ .n-status-complete {
386
+ color: var(--n-coral);
387
+ background: color-mix(in srgb, var(--n-coral) 15%, transparent);
388
+ }
389
+ .n-next-action {
390
+ margin: 0;
391
+ color: var(--n-muted);
392
+ font-size: 0.82rem;
393
+ text-align: right;
394
+ }
395
+ .n-next-action strong {
396
+ color: var(--n-ink);
397
+ }
398
+ .n-calendar-summary {
399
+ display: grid;
400
+ grid-template-columns: 1.4fr 0.8fr 1fr;
401
+ gap: 12px;
402
+ padding: 24px 0;
403
+ }
404
+ .n-summary-major, .n-summary-stat {
405
+ display: grid;
406
+ gap: 4px;
407
+ }
408
+ .n-summary-major strong {
409
+ color: var(--n-moss);
410
+ font-size: clamp(1.35rem, 3vw, 2rem);
411
+ line-height: 1;
412
+ }
413
+ .n-summary-stat strong {
414
+ font-size: 1.05rem;
415
+ }
416
+ .n-summary-major span, .n-summary-stat span {
417
+ color: var(--n-muted);
418
+ font-size: 0.76rem;
419
+ line-height: 1.3;
420
+ }
421
+ .n-phase-list {
422
+ display: grid;
423
+ gap: 0;
424
+ margin: 0;
425
+ padding: 0;
426
+ list-style: none;
427
+ }
428
+ .n-phase {
429
+ position: relative;
430
+ display: grid;
431
+ grid-template-columns: 34px 1fr;
432
+ gap: 12px;
433
+ padding: 0 0 22px;
434
+ }
435
+ .n-phase:not(:last-child)::after {
436
+ position: absolute;
437
+ top: 29px;
438
+ bottom: 0;
439
+ left: 16px;
440
+ width: 1px;
441
+ background: var(--n-line);
442
+ content: '';
443
+ }
444
+ .n-phase-marker {
445
+ position: relative;
446
+ z-index: 1;
447
+ display: grid;
448
+ place-items: center;
449
+ width: 32px;
450
+ height: 32px;
451
+ color: var(--n-muted);
452
+ background: var(--n-card);
453
+ border: 1px solid var(--n-line);
454
+ border-radius: 50%;
455
+ font-size: 0.8rem;
456
+ font-weight: 800;
457
+ }
458
+ .n-phase.is-active .n-phase-marker {
459
+ color: #fff;
460
+ background: var(--n-moss);
461
+ border-color: var(--n-moss);
462
+ }
463
+ .n-phase-content {
464
+ padding: 3px 0 0;
465
+ }
466
+ .n-phase-content h3 {
467
+ margin: 0;
468
+ font-size: 1rem;
469
+ }
470
+ .n-phase-date {
471
+ justify-content: flex-start;
472
+ margin: 5px 0 0;
473
+ color: var(--n-moss);
474
+ font-size: 0.85rem;
475
+ font-weight: 700;
476
+ }
477
+ .n-phase-detail {
478
+ margin: 5px 0 0;
479
+ color: var(--n-muted);
480
+ font-size: 0.78rem;
481
+ }
482
+ .sr-only {
483
+ position: absolute;
484
+ width: 1px;
485
+ height: 1px;
486
+ overflow: hidden;
487
+ clip-path: inset(50%);
488
+ white-space: nowrap;
489
+ }
490
+
491
+ @media (max-width: 760px) {
492
+ .n-seed-calendar {
493
+ grid-template-columns: 1fr;
494
+ }
495
+ .n-duration-grid {
496
+ grid-template-columns: repeat(3, minmax(0, 1fr));
497
+ }
498
+
499
+ .n-calendar-actions {
500
+ flex-wrap: wrap;
501
+ }
502
+ }
503
+
504
+ @media (max-width: 420px) {
505
+ .n-calendar-header {
506
+ align-items: flex-start;
507
+ flex-direction: column;
508
+ }
509
+ .n-next-action {
510
+ text-align: left;
511
+ }
512
+ .n-calendar-summary {
513
+ grid-template-columns: 1fr 1fr;
514
+ }
515
+ .n-summary-major {
516
+ grid-column: 1 / -1;
517
+ }
518
+ }
519
+
520
+ @media print {
521
+ @page {
522
+ size: 340px 208px;
523
+ margin: 0;
524
+ }
525
+
526
+ body * {
527
+ visibility: hidden;
528
+ }
529
+
530
+ .n-seed-calendar, .n-seed-calendar * {
531
+ visibility: visible;
532
+ }
533
+
534
+ .n-seed-calendar {
535
+ position: absolute;
536
+ top: 0;
537
+ left: 0;
538
+ display: block;
539
+ width: 340px;
540
+ min-height: 208px;
541
+ color: #111;
542
+ background: #fff;
543
+ border: 1px solid #111;
544
+ border-radius: 0;
545
+ box-shadow: none;
546
+ }
547
+
548
+ .n-calendar-controls, .n-calendar-results, .n-calendar-actions {
549
+ display: none;
550
+ }
551
+
552
+ .n-print-label {
553
+ display: grid;
554
+ gap: 4px;
555
+ padding: 30px;
556
+ font-size: 12px;
557
+ }
558
+ }
@@ -0,0 +1,10 @@
1
+ ---
2
+ import { SEORenderer } from '@jjlmoya/utils-shared';
3
+ import { seedStratificationCalendar } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ const { locale = 'en' } = Astro.props as { locale?: KnownLocale };
7
+ const content = await seedStratificationCalendar.i18n[locale]?.();
8
+ ---
9
+
10
+ {content?.seo?.length ? <SEORenderer content={{ locale, sections: content.seo }} /> : null}
@@ -0,0 +1,27 @@
1
+ import type { CalendarInput, TemperatureUnit } from './logic';
2
+
3
+ const STORAGE_KEY = 'jjlmoya-seed-stratification-calendar';
4
+
5
+ export interface CalendarState {
6
+ input: CalendarInput;
7
+ unit: TemperatureUnit;
8
+ }
9
+
10
+ export function loadCalendarState(fallback: CalendarInput): CalendarState {
11
+ try {
12
+ const raw = window.localStorage.getItem(STORAGE_KEY);
13
+ if (!raw) return { input: fallback, unit: 'metric' };
14
+ const stored = JSON.parse(raw) as Partial<CalendarState> & Partial<CalendarInput> & { sowingDate?: string };
15
+ const legacyInput = stored.sowingDate ? { ...fallback, mode: 'sowing-date' as const, anchorDate: stored.sowingDate } : fallback;
16
+ const input = stored.input ? { ...fallback, ...stored.input } : { ...legacyInput, ...stored };
17
+ return { input, unit: stored.unit === 'imperial' ? 'imperial' : 'metric' };
18
+ } catch {
19
+ return { input: fallback, unit: 'metric' };
20
+ }
21
+ }
22
+
23
+ export function saveCalendarState(input: CalendarInput, unit: TemperatureUnit): void {
24
+ try {
25
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify({ input, unit }));
26
+ } catch {}
27
+ }
@@ -0,0 +1,66 @@
1
+ export interface SeedStratificationCalendarUI extends Record<string, string> {
2
+ labelProfile: string;
3
+ labelMode: string;
4
+ labelModeSowing: string;
5
+ labelModeReady: string;
6
+ labelSowingDate: string;
7
+ labelReadyDate: string;
8
+ labelSoakDays: string;
9
+ labelWarmDays: string;
10
+ labelColdDays: string;
11
+ labelColdRange: string;
12
+ labelUnits: string;
13
+ labelMetric: string;
14
+ labelImperial: string;
15
+ labelFrom: string;
16
+ labelTo: string;
17
+ labelGenerate: string;
18
+ labelReset: string;
19
+ labelAddCalendar: string;
20
+ labelShare: string;
21
+ labelCopied: string;
22
+ labelPrint: string;
23
+ labelTechnique: string;
24
+ labelTodayStatus: string;
25
+ labelDayOf: string;
26
+ labelGantt: string;
27
+ labelTimeline: string;
28
+ labelNextAction: string;
29
+ labelCalendarStarts: string;
30
+ labelSowingDay: string;
31
+ labelDuration: string;
32
+ labelDays: string;
33
+ labelTemperature: string;
34
+ labelReady: string;
35
+ labelUpcoming: string;
36
+ labelActive: string;
37
+ labelComplete: string;
38
+ labelEditHint: string;
39
+ labelWarm: string;
40
+ labelCold: string;
41
+ labelSoak: string;
42
+ labelSow: string;
43
+ noteApple: string;
44
+ noteLavender: string;
45
+ noteMilkweed: string;
46
+ noteRose: string;
47
+ profileApple: string;
48
+ profileLavender: string;
49
+ profileMilkweed: string;
50
+ profileRose: string;
51
+ profileStrawberry: string;
52
+ profilePeach: string;
53
+ profileCherry: string;
54
+ profilePear: string;
55
+ profilePoppy: string;
56
+ profileSunflower: string;
57
+ profileTomato: string;
58
+ profileBasil: string;
59
+ instructionSoak: string;
60
+ instructionWarm: string;
61
+ instructionCold: string;
62
+ instructionSow: string;
63
+ emptyState: string;
64
+ warningDate: string;
65
+ warningTemperature: string;
66
+ }
package/src/tools.ts CHANGED
@@ -7,6 +7,7 @@ import { DIGITAL_CARBON_TOOL } from './tool/digitalCarbon/index';
7
7
  import { URBAN_GARDEN_PLANNER_TOOL } from './tool/urbanGardenPlanner/index';
8
8
  import { COMPOST_BIN_VOLUME_RATIO_CALCULATOR_TOOL } from './tool/compostBinVolumeRatioCalculator/index';
9
9
  import { WILDLIFE_CAMERA_TRAP_EFFORT_PLANNER_TOOL } from './tool/wildlifeCameraTrapEffortPlanner/index';
10
+ import { SEED_STRATIFICATION_CALENDAR_TOOL } from './tool/seedStratificationCalendar/index';
10
11
 
11
12
  export const ALL_TOOLS: ToolDefinition[] = [
12
13
  CRICKET_THERMOMETER_TOOL,
@@ -15,5 +16,6 @@ export const ALL_TOOLS: ToolDefinition[] = [
15
16
  DIGITAL_CARBON_TOOL,
16
17
  URBAN_GARDEN_PLANNER_TOOL,
17
18
  COMPOST_BIN_VOLUME_RATIO_CALCULATOR_TOOL,
18
- WILDLIFE_CAMERA_TRAP_EFFORT_PLANNER_TOOL
19
+ WILDLIFE_CAMERA_TRAP_EFFORT_PLANNER_TOOL,
20
+ SEED_STRATIFICATION_CALENDAR_TOOL
19
21
  ];