@flightlesslabs/dodo-ui 0.7.2 → 0.9.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 (138) hide show
  1. package/dist/index.d.ts +18 -2
  2. package/dist/index.js +11 -0
  3. package/dist/stories/components/Form/NumericInput/Events/Events.stories.svelte +126 -0
  4. package/dist/stories/components/Form/NumericInput/Events/Events.stories.svelte.d.ts +18 -0
  5. package/dist/stories/components/Form/NumericInput/NumericInput.stories.svelte +79 -0
  6. package/dist/stories/components/Form/NumericInput/NumericInput.stories.svelte.d.ts +21 -0
  7. package/dist/stories/components/Form/NumericInput/NumericInput.svelte +161 -0
  8. package/dist/stories/components/Form/NumericInput/NumericInput.svelte.d.ts +69 -0
  9. package/dist/stories/components/Form/NumericInput/Validation/Validation.stories.svelte +84 -0
  10. package/dist/stories/components/Form/NumericInput/Validation/Validation.stories.svelte.d.ts +18 -0
  11. package/dist/stories/components/Form/PasswordInput/Events/Events.stories.svelte +27 -6
  12. package/dist/stories/components/Form/PasswordInput/PasswordInput.svelte +5 -3
  13. package/dist/stories/components/Form/PasswordInput/PasswordInput.svelte.d.ts +7 -1
  14. package/dist/stories/components/Form/Select/Customize/Customize.stories.svelte +16 -1
  15. package/dist/stories/components/Form/Select/DropDownArrow/DropDownArrow.stories.svelte +59 -0
  16. package/dist/stories/components/Form/Select/DropDownArrow/DropDownArrow.stories.svelte.d.ts +18 -0
  17. package/dist/stories/components/Form/Select/Events/Events.stories.svelte +27 -0
  18. package/dist/stories/components/Form/Select/Positions/AutoPosition/AutoPosition.stories.svelte +54 -0
  19. package/dist/stories/components/Form/Select/Positions/AutoPosition/AutoPosition.stories.svelte.d.ts +18 -0
  20. package/dist/stories/components/Form/Select/Positions/Positions.stories.svelte +83 -0
  21. package/dist/stories/components/Form/Select/Positions/Positions.stories.svelte.d.ts +18 -0
  22. package/dist/stories/components/Form/Select/Select.svelte +110 -123
  23. package/dist/stories/components/Form/Select/Select.svelte.d.ts +22 -3
  24. package/dist/stories/components/Form/TextInput/Events/Events.stories.svelte +27 -0
  25. package/dist/stories/components/Form/TextInput/TextInput.svelte +5 -3
  26. package/dist/stories/components/Form/TextInput/TextInput.svelte.d.ts +10 -1
  27. package/dist/stories/components/Layout/Menu/DynamicMenu/Customize/Customize.stories.svelte +28 -0
  28. package/dist/stories/components/Layout/Menu/DynamicMenu/Customize/Customize.stories.svelte.d.ts +18 -0
  29. package/dist/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.stories.svelte +51 -0
  30. package/dist/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.stories.svelte.d.ts +22 -0
  31. package/dist/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.svelte +129 -0
  32. package/dist/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.svelte.d.ts +81 -0
  33. package/dist/stories/components/Layout/Menu/DynamicMenu/Events/Events.stories.svelte +46 -0
  34. package/dist/stories/components/Layout/Menu/DynamicMenu/Events/Events.stories.svelte.d.ts +18 -0
  35. package/dist/stories/components/Layout/Menu/DynamicMenu/KeybaordNavigation/KeybaordNavigation.stories.svelte +27 -0
  36. package/dist/stories/components/Layout/Menu/DynamicMenu/KeybaordNavigation/KeybaordNavigation.stories.svelte.d.ts +18 -0
  37. package/dist/stories/components/Layout/Menu/DynamicMenu/Options/OptionFormat.mdx +72 -0
  38. package/dist/stories/components/Layout/Menu/MenuItem/MenuItem.svelte.d.ts +1 -1
  39. package/dist/stories/developer tools/components/DynamicInput/DynamicInput.svelte +23 -4
  40. package/dist/stories/developer tools/components/DynamicInput/DynamicInput.svelte.d.ts +13 -2
  41. package/dist/stories/developer tools/components/DynamicInput/Events/Events.stories.svelte +115 -0
  42. package/dist/stories/developer tools/components/DynamicInput/Events/Events.stories.svelte.d.ts +18 -0
  43. package/dist/stories/developer tools/helpers/Numbers/cleanNumericString/cleanNumericString.d.ts +13 -0
  44. package/dist/stories/developer tools/helpers/Numbers/cleanNumericString/cleanNumericString.js +26 -0
  45. package/dist/stories/developer tools/helpers/Numbers/cleanNumericString/index.mdx +20 -0
  46. package/dist/stories/developer tools/helpers/Numbers/isValidNumberValue/index.mdx +71 -0
  47. package/dist/stories/developer tools/helpers/Numbers/isValidNumberValue/isValidNumberValue.d.ts +51 -0
  48. package/dist/stories/developer tools/helpers/Numbers/isValidNumberValue/isValidNumberValue.js +96 -0
  49. package/dist/stories/developer tools/helpers/logger/index.mdx +63 -0
  50. package/dist/stories/developer tools/helpers/logger/logger.d.ts +24 -0
  51. package/dist/stories/developer tools/helpers/logger/logger.js +31 -0
  52. package/package.json +15 -17
  53. package/src/lib/index.ts +33 -0
  54. package/src/lib/stories/Home.mdx +59 -0
  55. package/src/lib/stories/assets/dark-theme-toggle.png +0 -0
  56. package/src/lib/stories/components/Form/Button/Button.stories.svelte +61 -0
  57. package/src/lib/stories/components/Form/Button/Color/Color.stories.svelte +43 -0
  58. package/src/lib/stories/components/Form/Button/Events/Events.stories.svelte +36 -0
  59. package/src/lib/stories/components/Form/Button/IconButton/IconButton.stories.svelte +43 -0
  60. package/src/lib/stories/components/Form/Button/Roundness/Roundness.stories.svelte +23 -0
  61. package/src/lib/stories/components/Form/Button/Size/Size.stories.svelte +16 -0
  62. package/src/lib/stories/components/Form/Button/Variant/Variant.stories.svelte +18 -0
  63. package/src/lib/stories/components/Form/FormControl/FormControl.stories.svelte +28 -0
  64. package/src/lib/stories/components/Form/Label/Label.stories.svelte +13 -0
  65. package/src/lib/stories/components/Form/Message/Color/Color.stories.svelte +36 -0
  66. package/src/lib/stories/components/Form/Message/Message.stories.svelte +27 -0
  67. package/src/lib/stories/components/Form/Message/Size/Size.stories.svelte +22 -0
  68. package/src/lib/stories/components/Form/NumericInput/Events/Events.stories.svelte +134 -0
  69. package/src/lib/stories/components/Form/NumericInput/NumericInput.stories.svelte +84 -0
  70. package/src/lib/stories/components/Form/NumericInput/NumericInput.svelte +286 -0
  71. package/src/lib/stories/components/Form/NumericInput/Validation/Validation.stories.svelte +87 -0
  72. package/src/lib/stories/components/Form/PasswordInput/Events/Events.stories.svelte +132 -0
  73. package/src/lib/stories/components/Form/PasswordInput/PasswordInput.stories.svelte +59 -0
  74. package/src/lib/stories/components/Form/PasswordInput/PasswordInput.svelte +15 -3
  75. package/src/lib/stories/components/Form/PasswordInput/Roundness/Roundness.stories.svelte +20 -0
  76. package/src/lib/stories/components/Form/PasswordInput/Size/Size.stories.svelte +16 -0
  77. package/src/lib/stories/components/Form/PasswordInput/WithIcon/WithIcon.stories.svelte +31 -0
  78. package/src/lib/stories/components/Form/Select/Customize/Customize.stories.svelte +139 -0
  79. package/src/lib/stories/components/Form/Select/DropDownArrow/DropDownArrow.stories.svelte +63 -0
  80. package/src/lib/stories/components/Form/Select/Events/Events.stories.svelte +174 -0
  81. package/src/lib/stories/components/Form/Select/Options/OptionFormat.mdx +40 -0
  82. package/src/lib/stories/components/Form/Select/Positions/AutoPosition/AutoPosition.stories.svelte +58 -0
  83. package/src/lib/stories/components/Form/Select/Positions/Positions.stories.svelte +87 -0
  84. package/src/lib/stories/components/Form/Select/Roundness/Roundness.stories.svelte +32 -0
  85. package/src/lib/stories/components/Form/Select/Select.stories.svelte +121 -0
  86. package/src/lib/stories/components/Form/Select/Select.svelte +166 -146
  87. package/src/lib/stories/components/Form/Select/Size/Size.stories.svelte +28 -0
  88. package/src/lib/stories/components/Form/Select/WithIcon/WithIcon.stories.svelte +43 -0
  89. package/src/lib/stories/components/Form/TextInput/Events/Events.stories.svelte +125 -0
  90. package/src/lib/stories/components/Form/TextInput/Roundness/Roundness.stories.svelte +21 -0
  91. package/src/lib/stories/components/Form/TextInput/Size/Size.stories.svelte +17 -0
  92. package/src/lib/stories/components/Form/TextInput/TextInput.stories.svelte +43 -0
  93. package/src/lib/stories/components/Form/TextInput/TextInput.svelte +18 -3
  94. package/src/lib/stories/components/Form/TextInput/WithIcon/WithIcon.stories.svelte +47 -0
  95. package/src/lib/stories/components/Layout/Menu/DynamicMenu/Customize/Customize.stories.svelte +30 -0
  96. package/src/lib/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.stories.svelte +56 -0
  97. package/src/lib/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.svelte +262 -0
  98. package/src/lib/stories/components/Layout/Menu/DynamicMenu/Events/Events.stories.svelte +48 -0
  99. package/src/lib/stories/components/Layout/Menu/DynamicMenu/KeybaordNavigation/KeybaordNavigation.stories.svelte +29 -0
  100. package/src/lib/stories/components/Layout/Menu/DynamicMenu/Options/OptionFormat.mdx +72 -0
  101. package/src/lib/stories/components/Layout/Menu/Menu.stories.svelte +69 -0
  102. package/src/lib/stories/components/Layout/Menu/MenuItem/MenuItem.stories.svelte +34 -0
  103. package/src/lib/stories/components/Layout/Menu/MenuItem/MenuItem.svelte +1 -1
  104. package/src/lib/stories/components/Layout/Menu/MenuItem/Size/Size.stories.svelte +16 -0
  105. package/src/lib/stories/components/Layout/Menu/MenuItem/Type/Type.stories.svelte +21 -0
  106. package/src/lib/stories/components/Layout/Menu/Size/Size.stories.svelte +37 -0
  107. package/src/lib/stories/components/Layout/Paper/Color/Color.stories.svelte +63 -0
  108. package/src/lib/stories/components/Layout/Paper/Paper.stories.svelte +50 -0
  109. package/src/lib/stories/components/Layout/Paper/Roundness/Roundness.stories.svelte +25 -0
  110. package/src/lib/stories/components/Layout/Paper/Shadow/Shadow.stories.svelte +24 -0
  111. package/src/lib/stories/components/Layout/Separator/Color/Color.stories.svelte +19 -0
  112. package/src/lib/stories/components/Layout/Separator/Separator.stories.svelte +30 -0
  113. package/src/lib/stories/developer tools/Intro.mdx +9 -0
  114. package/src/lib/stories/developer tools/components/DynamicInput/DynamicInput.stories.svelte +53 -0
  115. package/src/lib/stories/developer tools/components/DynamicInput/DynamicInput.svelte +43 -3
  116. package/src/lib/stories/developer tools/components/DynamicInput/Events/Events.stories.svelte +121 -0
  117. package/src/lib/stories/developer tools/components/DynamicInput/Size/Size.stories.svelte +17 -0
  118. package/src/lib/stories/developer tools/components/InputEnclosure/InputEnclosure.stories.svelte +38 -0
  119. package/src/lib/stories/developer tools/components/InputEnclosure/Roundness/Roundness.stories.svelte +20 -0
  120. package/src/lib/stories/developer tools/components/InputEnclosure/Size/Size.stories.svelte +16 -0
  121. package/src/lib/stories/developer tools/components/InputEnclosure/WithIcon/WithIcon.stories.svelte +47 -0
  122. package/src/lib/stories/developer tools/components/Popper/Popper.stories.svelte +124 -0
  123. package/src/lib/stories/developer tools/components/Popper/PopperPopup/PopperPopup.stories.svelte +64 -0
  124. package/src/lib/stories/developer tools/components/Popper/Positions/AutoPosition/AutoPosition.stories.svelte +92 -0
  125. package/src/lib/stories/developer tools/components/Popper/Positions/Positions.stories.svelte +114 -0
  126. package/src/lib/stories/developer tools/components/UtilityButton/Size/Size.stories.svelte +25 -0
  127. package/src/lib/stories/developer tools/components/UtilityButton/UtilityButton.stories.svelte +30 -0
  128. package/src/lib/stories/developer tools/directives/clickOutside/index.mdx +25 -0
  129. package/src/lib/stories/developer tools/helpers/Numbers/cleanNumericString/cleanNumericString.ts +27 -0
  130. package/src/lib/stories/developer tools/helpers/Numbers/cleanNumericString/index.mdx +20 -0
  131. package/src/lib/stories/developer tools/helpers/Numbers/isValidNumberValue/index.mdx +71 -0
  132. package/src/lib/stories/developer tools/helpers/Numbers/isValidNumberValue/isValidNumberValue.ts +156 -0
  133. package/src/lib/stories/developer tools/helpers/logger/index.mdx +63 -0
  134. package/src/lib/stories/developer tools/helpers/logger/logger.ts +46 -0
  135. package/src/lib/stories/developer tools/philosophy/Colors/Colors.mdx +43 -0
  136. package/src/lib/stories/developer tools/philosophy/Colors/Colors.stories.svelte +22 -0
  137. package/src/lib/stories/developer tools/philosophy/Colors/Opacity.stories.svelte +11 -0
  138. package/src/lib/stories/developer tools/philosophy/Themes.mdx +23 -0
@@ -0,0 +1,30 @@
1
+ <script module lang="ts">
2
+ import { defineMeta } from '@storybook/addon-svelte-csf';
3
+ import UtilityButton from './UtilityButton.svelte';
4
+ import type { StoryBookArgTypes } from '$lib/storybook-types.js';
5
+ import Icon from '@iconify/svelte';
6
+ import { componentSizeArray } from '$lib/types/size.js';
7
+
8
+ export const storyUtilityButtonArgTypes: StoryBookArgTypes = {
9
+ size: {
10
+ control: { type: 'select' },
11
+ options: componentSizeArray,
12
+ },
13
+ };
14
+
15
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
16
+ const { Story } = defineMeta({
17
+ component: UtilityButton,
18
+ tags: ['autodocs'],
19
+ argTypes: storyUtilityButtonArgTypes,
20
+ });
21
+ </script>
22
+
23
+ <!-- Button with default style -->
24
+ <Story name="Default">
25
+ <Icon icon="mdi:eye" width="24" height="24" />
26
+ </Story>
27
+
28
+ <Story name="Disabled" args={{ disabled: true }}>
29
+ <Icon icon="mdi:eye" width="24" height="24" />
30
+ </Story>
@@ -0,0 +1,25 @@
1
+ import { Source } from '@storybook/blocks';
2
+
3
+ # Click Outside
4
+
5
+ Event that fires after clicking outside the target component
6
+
7
+ <Source
8
+ dark
9
+ language="js"
10
+ code={`
11
+ import { clickOutside } '@flightlesslabs/dodo-ui';
12
+ `}
13
+ />
14
+
15
+ Attach it to a component
16
+
17
+ <Source
18
+ dark
19
+ language="js"
20
+ code={`
21
+ <div
22
+ use:clickOutside={onClickOutside}
23
+ ...
24
+ `}
25
+ />
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Cleans the input string by removing all characters except numeric digits (0-9) and a single decimal point.
3
+ * Only the first decimal point is retained; all subsequent dots are removed.
4
+ *
5
+ * @param {string} input - The input string to be cleaned.
6
+ * @returns {string} - A string containing only digits and at most one decimal point.
7
+ *
8
+ * @example
9
+ * cleanNumericString("abc123.45.67def"); // returns "123.4567"
10
+ * cleanNumericString("a1b2c3"); // returns "123"
11
+ * cleanNumericString("...12.3.4..5"); // returns "12.345"
12
+ */
13
+ export default function cleanNumericString(input: string): string {
14
+ // Remove all characters except digits and dots
15
+ const filtered = input.replace(/[^0-9.]/g, '');
16
+
17
+ // Split by dot to separate parts
18
+ const parts = filtered.split('.');
19
+
20
+ if (parts.length === 1) {
21
+ // No dot present, just digits
22
+ return parts[0];
23
+ } else {
24
+ // Keep only first dot, join the rest parts without dots
25
+ return parts[0] + '.' + parts.slice(1).join('');
26
+ }
27
+ }
@@ -0,0 +1,20 @@
1
+ import { Source } from '@storybook/blocks';
2
+
3
+ # cleanNumericString
4
+
5
+ Cleans the input string by removing all characters except numeric digits (0-9) and a single decimal point.
6
+ Only the first decimal point is retained; all subsequent dots are removed.
7
+
8
+ ---
9
+
10
+ ## Basic Usage
11
+
12
+ <Source
13
+ dark
14
+ language="ts"
15
+ code={`
16
+ import { cleanNumericString } from '@flightlesslabs/dodo-ui';
17
+
18
+ const result = cleanNumericString("abc123.45.67def"); // result === "123.4567"
19
+ `}
20
+ />
@@ -0,0 +1,71 @@
1
+ import { Source } from '@storybook/blocks';
2
+
3
+ # isValidNumberValue
4
+
5
+ Utility function to validate whether a string is a valid number based on customizable settings including minimum, maximum, decimal places, and allowance of negative numbers.
6
+
7
+ ---
8
+
9
+ ## Basic Usage
10
+
11
+ Validates a string as a number with default settings (no decimals allowed, no negatives allowed, strict checking):
12
+
13
+ <Source
14
+ dark
15
+ language="ts"
16
+ code={`
17
+ import { isValidNumberValue } from '@flightlesslabs/dodo-ui';
18
+
19
+ const result = isValidNumberValue("123");
20
+ console.log(result); // true
21
+ `}
22
+ />
23
+
24
+ ---
25
+
26
+ ## With Settings
27
+
28
+ Customize validation rules:
29
+
30
+ - `min` — minimum allowed value (inclusive)
31
+ - `max` — maximum allowed value (inclusive)
32
+ - `allowNegativeValues` — whether negatives are allowed
33
+ - `decimalPlaces` — max decimal places allowed
34
+ - `log` — enable detailed logging
35
+ - `strict` — Strict checking, Full text - keep it enabled, Partial text - keep it disabled
36
+
37
+ <Source
38
+ dark
39
+ language="ts"
40
+ code={`
41
+ import { isValidNumberValue } from '@flightlesslabs/dodo-ui';
42
+
43
+ const result1 = isValidNumberValue("123.456", { decimalPlaces: 3, log: true });
44
+ const result2 = isValidNumberValue("-50", { allowNegativeValues: true, min: -100 });
45
+ const result3 = isValidNumberValue("200", { max: 150 });
46
+
47
+ const result4 = isValidNumberValue("-", { allowNegativeValues: true });
48
+ const result5 = isValidNumberValue("-", { allowNegativeValues: true, strict: false });
49
+
50
+ console.log(result1); // true
51
+ console.log(result2); // true
52
+ console.log(result3); // false (exceeds max)
53
+ console.log(result4); // false (fails in strict check)
54
+ console.log(result5); // true (pass in strict check)
55
+ `}
56
+ />
57
+
58
+ ---
59
+
60
+ ## Type Definition
61
+
62
+ ```ts
63
+ export type IsValidNumberValueSettings = {
64
+ min?: number;
65
+ max?: number;
66
+ allowNegativeValues?: boolean;
67
+ decimalPlaces?: number;
68
+ log?: boolean;
69
+ strict?: boolean;
70
+ };
71
+ ```
@@ -0,0 +1,156 @@
1
+ import createLogger from '../../logger/logger.js';
2
+
3
+ export type IsValidNumberValueSettings = {
4
+ /**
5
+ * Minimum allowed numeric value (inclusive).
6
+ */
7
+ min?: number;
8
+
9
+ /**
10
+ * Maximum allowed numeric value (inclusive).
11
+ */
12
+ max?: number;
13
+
14
+ /**
15
+ * Whether negative numbers are allowed.
16
+ * Defaults to false.
17
+ */
18
+ allowNegativeValues?: boolean;
19
+
20
+ /**
21
+ * Maximum allowed decimal places.
22
+ * Defaults to 0 (no decimals allowed).
23
+ */
24
+ decimalPlaces?: number;
25
+
26
+ /**
27
+ * Whether to enable logging.
28
+ * Defaults to false.
29
+ */
30
+ log?: boolean;
31
+
32
+ /**
33
+ * Strict checking, Full text - keep it enabled, Partial text - keep it disabled
34
+ * Defaults to true.
35
+ */
36
+ strict?: boolean;
37
+ };
38
+
39
+ /**
40
+ * Checks if the input string is a valid numeric string.
41
+ * Allows integers, decimals, negative numbers, and scientific notation.
42
+ *
43
+ * @param str - Input string to validate.
44
+ * @returns True if string is numeric, false otherwise.
45
+ */
46
+ function isNumericString(str: string): boolean {
47
+ if (typeof str !== 'string') return false;
48
+ const trimmed = str.trim();
49
+ if (trimmed === '') return false;
50
+ const num = Number(trimmed);
51
+ return !isNaN(num) && isFinite(num);
52
+ }
53
+
54
+ /**
55
+ * Validates whether a string represents a valid number based on provided settings.
56
+ *
57
+ * @param value - The string to validate as a number.
58
+ * @param settings - Optional validation settings.
59
+ * @param settings.min - Minimum allowed value (inclusive).
60
+ * @param settings.max - Maximum allowed value (inclusive).
61
+ * @param settings.allowNegativeValues - Whether negative numbers are allowed.
62
+ * @param settings.decimalPlaces - Maximum allowed decimal places.
63
+ * @param settings.log - Whether to enable detailed logging.
64
+ * @param settings.strict - Whether to enable Strict checking, Full text - keep it enabled, Partial text - keep it disabled
65
+ *
66
+ * @returns True if the value is a valid number according to the settings; otherwise false.
67
+ *
68
+ * @example
69
+ * ```ts
70
+ * isValidNumberValue("123.45", { decimalPlaces: 2, log: true });
71
+ * isValidNumberValue("-50", { allowNegativeValues: true, min: -100 });
72
+ * ```
73
+ */
74
+ export default function isValidNumberValue(
75
+ value: string,
76
+ settings?: IsValidNumberValueSettings,
77
+ ): boolean {
78
+ const allowNegativeValues = settings?.allowNegativeValues || false;
79
+ const decimalPlaces = settings?.decimalPlaces || 0;
80
+ const valueFormatted = value.trim();
81
+ const log = settings?.log || false;
82
+ const logger = createLogger({
83
+ label: 'isValidNumberValue',
84
+ show: log,
85
+ });
86
+ const min = settings?.min;
87
+ const max = settings?.max;
88
+ const strict = settings?.strict === false ? false : true;
89
+
90
+ logger.info(`Validating value: "${valueFormatted}"`);
91
+
92
+ if (strict && !isNumericString(valueFormatted)) {
93
+ logger.warn('Invalid input: strict checking is enaabled and the text failed the checks');
94
+ return false;
95
+ }
96
+
97
+ if (valueFormatted === '') {
98
+ logger.info('Valid input: Blank value');
99
+ return true;
100
+ }
101
+
102
+ if (allowNegativeValues && valueFormatted === '-') {
103
+ logger.info(`Valid input: Single '-' sign allowed as a negative placeholder.`);
104
+ return true;
105
+ }
106
+
107
+ if (!decimalPlaces && valueFormatted.includes('.')) {
108
+ logger.warn('Invalid input: Decimals not allowed');
109
+ return false;
110
+ }
111
+
112
+ const dotCount = (valueFormatted.match(/\./g) || []).length;
113
+
114
+ if (dotCount > 1) {
115
+ logger.warn('Invalid input: More than one decimal point detected.');
116
+ return false;
117
+ }
118
+
119
+ const parts = valueFormatted.split('.');
120
+
121
+ if (parts[1]?.length > decimalPlaces) {
122
+ logger.warn(
123
+ `Invalid input: Number has ${parts[1].length} decimal places, exceeding the allowed limit of ${decimalPlaces}.`,
124
+ );
125
+ return false;
126
+ }
127
+
128
+ if (!isNumericString(valueFormatted)) {
129
+ logger.warn('Invalid input: String is not a valid number.');
130
+ return false;
131
+ }
132
+
133
+ const numericValue = Number(valueFormatted);
134
+
135
+ if (!allowNegativeValues && numericValue < 0) {
136
+ logger.warn('Invalid input: Negative numbers are not allowed.');
137
+ return false;
138
+ }
139
+
140
+ if (min !== undefined && numericValue < min) {
141
+ logger.warn(
142
+ `Invalid input: Number ${numericValue} is less than the minimum allowed value of ${min}.`,
143
+ );
144
+ return false;
145
+ }
146
+
147
+ if (max !== undefined && numericValue > max) {
148
+ logger.warn(
149
+ `Invalid input: Number ${numericValue} exceeds the maximum allowed value of ${max}.`,
150
+ );
151
+ return false;
152
+ }
153
+
154
+ logger.info('Validation passed: Input is a valid number according to the provided settings.');
155
+ return true;
156
+ }
@@ -0,0 +1,63 @@
1
+ import { Source } from '@storybook/blocks';
2
+
3
+ # Logger Utility
4
+
5
+ A customizable logger function that supports:
6
+
7
+ - Log levels (`info`, `warn`, `error`)
8
+ - Optional labels
9
+ - A `show` flag to toggle logging
10
+ - Console output with timestamps
11
+
12
+ ## Import
13
+
14
+ Import the logger creation function:
15
+
16
+ <Source dark language="ts" code={`import { createLogger } from '@flightlesslabs/dodo-ui';`} />
17
+
18
+ ## Basic Usage
19
+
20
+ Create a logger and log different types of messages:
21
+
22
+ <Source
23
+ dark
24
+ language="ts"
25
+ code={`const logger = createLogger({
26
+ label: 'AuthService',
27
+ });
28
+
29
+ logger.info('User logged in');
30
+ logger.warn('Token is about to expire');
31
+ logger.error('Login failed', new Error('Invalid credentials'));
32
+ `}
33
+ />
34
+
35
+ ## Disable Logging
36
+
37
+ You can use the \`show\` flag to completely silence the logger (e.g., in production):
38
+
39
+ <Source
40
+ dark
41
+ language="ts"
42
+ code={`const logger = createLogger({
43
+ show: false,
44
+ });
45
+
46
+ logger.info('This will not be logged');
47
+ `}
48
+ />
49
+
50
+ ## Level Filtering
51
+
52
+ The logger will only show messages **at or above** the configured `level`:
53
+
54
+ <Source
55
+ dark
56
+ language="ts"
57
+ code={`const logger = createLogger();
58
+
59
+ logger.info('This will NOT show');
60
+ logger.warn('This WILL show');
61
+ logger.error('This WILL show');
62
+ `}
63
+ />
@@ -0,0 +1,46 @@
1
+ export type LogLevel = 'info' | 'warn' | 'error';
2
+
3
+ export interface LoggerOptions {
4
+ /**
5
+ * Optional label to prefix log entries.
6
+ */
7
+ label?: string;
8
+
9
+ /**
10
+ * Whether to actually show logs.
11
+ * Defaults to true.
12
+ */
13
+ show?: boolean;
14
+ }
15
+
16
+ /**
17
+ * Formats the log message with timestamp, label, and level.
18
+ */
19
+ export function formatPrefix(level: LogLevel, label?: string): string {
20
+ const timestamp = new Date().toISOString();
21
+ const labelPart = label ? `[${label}]` : '';
22
+ return `[${timestamp}] ${labelPart} [${level.toUpperCase()}]`;
23
+ }
24
+
25
+ /**
26
+ * Creates a logger that logs every call unless disabled by show=false.
27
+ */
28
+ export default function createLogger(options: LoggerOptions = {}) {
29
+ const { label, show = true } = options;
30
+
31
+ function shouldLog() {
32
+ return show;
33
+ }
34
+
35
+ return {
36
+ info: (msg: unknown, ...optionalParams: unknown[]) => {
37
+ if (shouldLog()) console.info(formatPrefix('info', label), msg, ...optionalParams);
38
+ },
39
+ warn: (msg: unknown, ...optionalParams: unknown[]) => {
40
+ if (shouldLog()) console.warn(formatPrefix('warn', label), msg, ...optionalParams);
41
+ },
42
+ error: (msg: unknown, ...optionalParams: unknown[]) => {
43
+ if (shouldLog()) console.error(formatPrefix('error', label), msg, ...optionalParams);
44
+ },
45
+ };
46
+ }
@@ -0,0 +1,43 @@
1
+ import { Meta, Story, Source } from '@storybook/blocks';
2
+ import * as ColorsStories from './Colors.stories.svelte';
3
+ import * as OpacityStories from './Opacity.stories.svelte';
4
+
5
+ <Meta of={ColorsStories} />
6
+
7
+ # Colors
8
+
9
+ We are using an extensive color pallet identical to [Tailwind Css](https://tailwindcss.com/docs/colors) Colors. The colors are adjusted for dark and light themes.
10
+
11
+ ## Main Colors
12
+
13
+ <Story of={ColorsStories.Main} />
14
+
15
+ Greyscale colors
16
+
17
+ <Story of={ColorsStories.ColorsNeutral} />
18
+
19
+ Constant Colors
20
+
21
+ <Story of={ColorsStories.ColorsConstant} />
22
+
23
+ ## Base Color
24
+
25
+ <Story of={ColorsStories.ColorsBase} />
26
+
27
+ Greyscale colors
28
+
29
+ <Story of={ColorsStories.BaseColorsNeutral} />
30
+
31
+ ## Adjusting opacity
32
+
33
+ Opacity can be adjusted using css `color-mix` function.
34
+
35
+ <Source
36
+ dark
37
+ language="css"
38
+ code={`
39
+ color-mix(in oklab, var(--dodo-color-primary-800) 10%, transparent)
40
+ `}
41
+ />
42
+
43
+ <Story of={OpacityStories.Main} meta={OpacityStories} />
@@ -0,0 +1,22 @@
1
+ <script module lang="ts">
2
+ import { defineMeta } from '@storybook/addon-svelte-csf';
3
+ import Colors from './Colors.svelte';
4
+
5
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
6
+ const { Story } = defineMeta({
7
+ component: Colors,
8
+ args: {
9
+ swatchType: 'colors',
10
+ },
11
+ });
12
+ </script>
13
+
14
+ <Story name="Main" />
15
+
16
+ <Story name="ColorsNeutral" args={{ swatchType: 'colors-neutral' }} />
17
+
18
+ <Story name="ColorsConstant" args={{ swatchType: 'colors-constant' }} />
19
+
20
+ <Story name="ColorsBase" args={{ swatchType: 'base-colors' }} />
21
+
22
+ <Story name="BaseColorsNeutral" args={{ swatchType: 'base-colors-neutral' }} />
@@ -0,0 +1,11 @@
1
+ <script module lang="ts">
2
+ import { defineMeta } from '@storybook/addon-svelte-csf';
3
+ import Opacity from './Opacity.svelte';
4
+
5
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
6
+ const { Story } = defineMeta({
7
+ component: Opacity,
8
+ });
9
+ </script>
10
+
11
+ <Story name="Main" />
@@ -0,0 +1,23 @@
1
+ import { Source } from '@storybook/blocks';
2
+ import darkThemeToggleImage from '$lib/stories/assets/dark-theme-toggle.png';
3
+
4
+ # Themes
5
+
6
+ ## Dark theme
7
+
8
+ dark theme can be activated by adding `.dodo-theme--dark` class on the top container.
9
+
10
+ <Source
11
+ dark
12
+ language="html"
13
+ code={`
14
+ <body class="dodo-theme--dark">
15
+ ...
16
+ `}
17
+ />
18
+
19
+ ## Toggle theme in documentation
20
+
21
+ Use the moon icon to toogle theme in documentation mode
22
+
23
+ <img src={darkThemeToggleImage} />