@qr-platform/qr-code.js 0.10.1 → 0.10.2
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/CHANGELOG.md +6 -0
- package/docs/api-reference-guide.md +5 -1
- package/docs/documentation.md +5 -4
- package/docs/ft009-settings-option-continuation-plan.md +124 -0
- package/docs/ft009-settings-option-plan.md +254 -0
- package/docs/typescript-types-definitions.md +55 -0
- package/docs/usage-guide.md +146 -3
- package/lib/core/qr-code-js.d.ts +14 -1
- package/lib/index.d.ts +17 -70
- package/lib/index.js +1 -1
- package/lib/lib/tiny-colors.d.ts +234 -0
- package/lib/node/core/qr-code-js.d.ts +14 -1
- package/lib/node/index.d.ts +17 -70
- package/lib/node/lib/tiny-colors.d.ts +234 -0
- package/lib/node/node.d.ts +16 -0
- package/lib/node/plugins/QRBorderPlugin.d.ts +1 -0
- package/lib/node/types/settings-options.d.ts +20 -0
- package/lib/node/types/style-options.d.ts +1 -0
- package/lib/node/types/text-options.d.ts +1 -0
- package/lib/node/utils/merge.d.ts +1 -0
- package/lib/node/utils/options.d.ts +3 -3
- package/lib/node/utils/style-mapper.d.ts +0 -5
- package/lib/node.d.ts +16 -0
- package/lib/node.js +1 -1
- package/lib/plugins/QRBorderPlugin.d.ts +1 -0
- package/lib/types/settings-options.d.ts +20 -0
- package/lib/types/style-options.d.ts +1 -0
- package/lib/types/text-options.d.ts +1 -0
- package/lib/utils/merge.d.ts +1 -0
- package/lib/utils/options.d.ts +3 -3
- package/lib/utils/style-mapper.d.ts +0 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -95,6 +95,8 @@ qrCode.append(document.getElementById('qr-container'));
|
|
|
95
95
|
| `setBorder` | `borderNameOrOptions: string \| RecursivePartial<BorderOptions>` | Sets a global default border configuration (by name or options object) for subsequent instances. Returns `void`. |
|
|
96
96
|
| `setBorderId` | `borderId: string` | Sets a global default border configuration by its ID. Returns `void`. |
|
|
97
97
|
| `setImage` | `imageUrl: string \| DataURL \| null, options?: { override?: boolean }` | Sets a global default image URL for subsequent instances. With `{ override: true }`, the image will take precedence over any instance-specific images.
|
|
98
|
+
| `settings` | `settings: SettingsOptions \| null` | **(Static)** Sets global default settings from a `SettingsOptions` object. This will override/reset any previously set static template, style, text, or border. Returns `typeof QRCodeJs`. |
|
|
99
|
+
| `setSettings` | `settings: SettingsOptions` | **(Instance)** Applies settings from a `SettingsOptions` object to the current instance, completely replacing its current options. Returns `Promise<void>`. |
|
|
98
100
|
| `useTemplate` | `templateNameOrOptions: string \| RecursivePartial<Options>` | Initiates a builder pattern pre-configured with a template (by name or options object). Returns `QRCodeBuilder`. |
|
|
99
101
|
| `useTemplateId` | `templateId: string` | Initiates a builder pattern pre-configured with a template by its ID. Returns `QRCodeBuilder`. |
|
|
100
102
|
| `useStyle` | `styleNameOrOptions: string \| StyleOptions` | Initiates a builder pattern pre-configured with a style (by name or options object). Returns `QRCodeBuilder`. |
|
|
@@ -158,7 +160,8 @@ The `borderOptions` object is a premium feature that allows you to add decorativ
|
|
|
158
160
|
| `style.fontSize` | `number` | `28` | The font size for the text in pixels. |
|
|
159
161
|
| `style.fontColor` | `string` | `'#ffffff'` | The color of the text. |
|
|
160
162
|
| `style.letterSpacing` | `number` | `0` | The letter spacing for the text in pixels. |
|
|
161
|
-
| `style.
|
|
163
|
+
| `style.textTransform` | `'uppercase' \| 'lowercase' \| 'capitalize'` | `uppercase` | The text transformation style. |
|
|
164
|
+
| `style.fontWeight` | `'normal' \| 'bold'` | `'bold'` | The font weight for the text. |
|
|
162
165
|
|
|
163
166
|
### Enums
|
|
164
167
|
|
|
@@ -300,6 +303,7 @@ const qr3 = QRCodeJs.useTemplate('basic')
|
|
|
300
303
|
| `useBorder` | `borderNameOrOptions: string \| BorderOptions` | Applies border configuration (by name or options object) to the current configuration. Returns `this`. |
|
|
301
304
|
| `useBorderId` | `borderId: string` | Applies border configuration by its ID to the current configuration. Returns `this`. |
|
|
302
305
|
| `useImage` | `imageUrl: string, options?: { override?: boolean }` | Sets the image URL for the current configuration. With `{ override: true}`, the image will take precedence over any image set in final options. Returns `this`. |
|
|
306
|
+
| `useSettings` | `settings: SettingsOptions` | Applies a comprehensive `SettingsOptions` object to the builder. This will override/reset any previously set builder configurations (template, style, text, border, image, data). Returns `this`. |
|
|
303
307
|
| `options` | `options: RecursivePartial<Options>` | Merges the provided `Options` into the current configuration and returns the final `QRCodeJs` instance. |
|
|
304
308
|
| `build` | - | Creates and returns the final `QRCodeJs` instance based on the accumulated configuration. |
|
|
305
309
|
### See Also
|
package/docs/documentation.md
CHANGED
|
@@ -698,6 +698,7 @@ Options for adding decorative borders around the QR code. Borders can be configu
|
|
|
698
698
|
fontFace: 'Helvetica',
|
|
699
699
|
fontSize: 28,
|
|
700
700
|
fontColor: '#ffffff',
|
|
701
|
+
textTransform: 'uppercase',
|
|
701
702
|
letterSpacing: 2,
|
|
702
703
|
fontWeight: 'bold'
|
|
703
704
|
}
|
|
@@ -826,10 +827,10 @@ QRCode.js provides dedicated methods for managing text on QR code borders, allow
|
|
|
826
827
|
- **Example**:
|
|
827
828
|
```typescript
|
|
828
829
|
// Set global text using a predefined template ID
|
|
829
|
-
QRCodeJs.setTextId('visit-website
|
|
830
|
+
QRCodeJs.setTextId('scan-to-visit-website');
|
|
830
831
|
|
|
831
832
|
// With override option
|
|
832
|
-
QRCodeJs.setTextId('lost-found
|
|
833
|
+
QRCodeJs.setTextId('lost-found', { override: true });
|
|
833
834
|
|
|
834
835
|
// Clear global text
|
|
835
836
|
QRCodeJs.setTextId(null);
|
|
@@ -884,11 +885,11 @@ QRCode.js provides dedicated methods for managing text on QR code borders, allow
|
|
|
884
885
|
- **Example**:
|
|
885
886
|
```typescript
|
|
886
887
|
// Start builder with a predefined text template by ID
|
|
887
|
-
const qrCode = QRCodeJs.useTextId('visit-website
|
|
888
|
+
const qrCode = QRCodeJs.useTextId('scan-to-visit-website')
|
|
888
889
|
.options({ data: 'https://example.com' });
|
|
889
890
|
|
|
890
891
|
// With override option
|
|
891
|
-
const qrWithOverride = QRCodeJs.useTextId('scan-me
|
|
892
|
+
const qrWithOverride = QRCodeJs.useTextId('scan-me', { override: true })
|
|
892
893
|
.options({ data: 'https://example.com' });
|
|
893
894
|
```
|
|
894
895
|
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# Feature Task FT009 - Settings Option - Continuation Plan
|
|
2
|
+
|
|
3
|
+
## 1. Original Task Description (FT009)
|
|
4
|
+
|
|
5
|
+
**Feature:** Settings Option
|
|
6
|
+
**Task Description:** Add a mechanism to configure QR code instances using a comprehensive `SettingsOptions` object. This was initially planned as an instance method `setSettings()` and a static builder-style method `QRCodeJs.settings()`. The requirements evolved to include a `useSettings()` method for the `QRCodeBuilder` and to make the instance-level application a static utility method.
|
|
7
|
+
|
|
8
|
+
**Core Requirements:**
|
|
9
|
+
* Provide a centralized way to configure multiple QR code properties: `id`, `name`, `description`, `data`, `image`, `template`, `templateId`, `style`, `styleId`, `text`, `textId`, `border`, `borderId`, and a general `options` override.
|
|
10
|
+
* Ensure this new configuration method interacts correctly with existing setup methods, generally by overriding previous settings.
|
|
11
|
+
|
|
12
|
+
## 2. Current Implementation Status
|
|
13
|
+
|
|
14
|
+
### 2.1. Core Class Changes ([`src/core/qr-code-js.ts`](src/core/qr-code-js.ts))
|
|
15
|
+
* **`SettingsOptions` Type:** Defined in [`src/types/settings-options.ts`](src/types/settings-options.ts). It includes:
|
|
16
|
+
```typescript
|
|
17
|
+
export interface SettingsOptions {
|
|
18
|
+
id?: string;
|
|
19
|
+
name?: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
data?: string;
|
|
22
|
+
image?: string | Buffer | Blob;
|
|
23
|
+
template?: string | RecursivePartial<Options>;
|
|
24
|
+
templateId?: string;
|
|
25
|
+
style?: string | StyleOptions;
|
|
26
|
+
styleId?: string;
|
|
27
|
+
text?: string | TextOptions;
|
|
28
|
+
textId?: string;
|
|
29
|
+
border?: string | RecursivePartial<BorderOptions>;
|
|
30
|
+
borderId?: string;
|
|
31
|
+
options?: RecursivePartial<Options>;
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
* **Static `setSettings` Method:**
|
|
35
|
+
* A `public static async setSettings(instance: QRCodeJs, settings: SettingsOptions): Promise<void>` method has been added to `QRCodeJs`.
|
|
36
|
+
* This method applies the provided `SettingsOptions` to a given `QRCodeJs` instance.
|
|
37
|
+
* It completely replaces the instance's current options by:
|
|
38
|
+
1. Starting with `baseQRTemplateOptions`.
|
|
39
|
+
2. Applying `template`, `style`, `text`, `border` from the `settings` object.
|
|
40
|
+
3. Setting `newOptions.image = settings.image` if `settings.image` is provided.
|
|
41
|
+
4. Setting `newOptions.data = settings.data` if `settings.data` is provided. If not, it attempts to use `settings.options.data`. If still not present, it retains `instance.options.data`.
|
|
42
|
+
5. Merging `settings.options` for any other direct overrides.
|
|
43
|
+
6. Validating and sanitizing the resulting options.
|
|
44
|
+
7. Calling `await instance.update()`.
|
|
45
|
+
* **Removed Static Configuration:** The previously planned static `QRCodeJs.settings()` method (that would set static defaults like `_selectedSettings`) and related static properties (`_selectedSettings`, `_selectedData`) have been removed from `QRCodeJs` as per user feedback.
|
|
46
|
+
|
|
47
|
+
### 2.2. Documentation
|
|
48
|
+
* [`docs/typescript-types-definitions.md`](docs/typescript-types-definitions.md): Updated with the `SettingsOptions` interface.
|
|
49
|
+
* [`docs/api-reference-guide.md`](docs/api-reference-guide.md): Updated to reflect the new static `QRCodeJs.setSettings(instance, settings)` method and remove the old static `QRCodeJs.settings()` method.
|
|
50
|
+
* [`docs/usage-guide.md`](docs/usage-guide.md): Updated with examples for the new static `QRCodeJs.setSettings(instance, settings)` method.
|
|
51
|
+
|
|
52
|
+
### 2.3. Unit Tests
|
|
53
|
+
* [`tests/node/node.settings.test.ts`](tests/node/node.settings.test.ts): Initial tests for the static `setSettings(instance, settings)` method have been created and partially debugged. Import paths and type assertions have been refined.
|
|
54
|
+
|
|
55
|
+
## 3. Remaining Tasks
|
|
56
|
+
|
|
57
|
+
### 3.1. Implement `useSettings` in `QRCodeBuilder`
|
|
58
|
+
This is the primary remaining coding task. The `useSettings` method needs to be added to the `QRCodeBuilder` class in both:
|
|
59
|
+
* [`src/index.ts`](src/index.ts) (for browser environment)
|
|
60
|
+
* [`src/node.ts`](src/node.ts) (for Node.js environment)
|
|
61
|
+
|
|
62
|
+
**`QRCodeBuilder.useSettings(settings: SettingsOptions): this` Method Details:**
|
|
63
|
+
* **Store Settings:**
|
|
64
|
+
* Add a new protected property to `QRCodeBuilder`: `protected _settingsSource: SettingsOptions | null = null;`
|
|
65
|
+
* The `useSettings` method will set `this._settingsSource = settings;`.
|
|
66
|
+
* **Override Behavior:**
|
|
67
|
+
* Calling `useSettings` must reset/nullify all other builder-specific configuration sources to ensure it takes precedence over any prior `useTemplate()`, `useStyle()`, `useBorder()`, `useText()`, `useImage()` calls, and `_initialOptions`. This includes:
|
|
68
|
+
* `this._templateSource = null;`
|
|
69
|
+
* `this._isTemplateById = false;`
|
|
70
|
+
* `this._borderSource = null;`
|
|
71
|
+
* `this._isBorderById = false;`
|
|
72
|
+
* `this._styleSource = null;`
|
|
73
|
+
* `this._isStyleById = false;`
|
|
74
|
+
* `this._imageSource = null;`
|
|
75
|
+
* `this._imageOverride = false;`
|
|
76
|
+
* `this._textSource = null;`
|
|
77
|
+
* `this._isTextById = false;`
|
|
78
|
+
* `this._textOverride = false;`
|
|
79
|
+
* `this._initialOptions = null;`
|
|
80
|
+
* **Modify `_resolveAndMergeConfig(finalOptions: RecursivePartial<Options> = {})` in `QRCodeBuilder`:**
|
|
81
|
+
* **Priority for `_settingsSource`:**
|
|
82
|
+
1. If `this._settingsSource` is set:
|
|
83
|
+
* Initialize `resolvedConfig = mergeDeep({}, baseQRTemplateOptions)`.
|
|
84
|
+
* Apply `template/templateId` from `this._settingsSource` to `resolvedConfig`.
|
|
85
|
+
* Apply `style/styleId` from `this._settingsSource` (mapping style options) to `resolvedConfig`.
|
|
86
|
+
* Apply `border/borderId` from `this._settingsSource` to `resolvedConfig`.
|
|
87
|
+
* Apply `text/textId` from `this._settingsSource` (mapping to `borderOptions.decorations`) to `resolvedConfig`.
|
|
88
|
+
* If `this._settingsSource.image` is defined, set `resolvedConfig.image = this._settingsSource.image;`.
|
|
89
|
+
* If `this._settingsSource.data` is defined, set `resolvedConfig.data = this._settingsSource.data;`.
|
|
90
|
+
* Merge `this._settingsSource.options` into `resolvedConfig`.
|
|
91
|
+
* **Else (no `_settingsSource`):**
|
|
92
|
+
* Follow the existing logic: apply `_initialOptions`, then `_templateSource`, `_borderSource`, `_styleSource`, `_imageSource` (non-override), `_textSource` (non-override).
|
|
93
|
+
* **Final Merge & Overrides:**
|
|
94
|
+
* Merge `finalOptions` (from a subsequent `.options()` call) into `resolvedConfig`. This allows `.options()` to override settings from `useSettings`.
|
|
95
|
+
* The existing `_imageOverride` and `_textOverride` logic should apply last. If `useImage(..., {override:true})` or `useText(..., {override:true})` is called *after* `useSettings()`, it effectively clears `_settingsSource` (because `useSettings` resets those specific sources) and these specific overrides would then apply as intended.
|
|
96
|
+
|
|
97
|
+
### 3.2. Unit Testing
|
|
98
|
+
* Add comprehensive unit tests for `QRCodeBuilder.useSettings` in both [`tests/node/node.settings.test.ts`](tests/node/node.settings.test.ts) and potentially a new browser-specific test file if behavior differs or requires DOM.
|
|
99
|
+
* Tests should cover:
|
|
100
|
+
* `useSettings` correctly applying all properties from `SettingsOptions`.
|
|
101
|
+
* `useSettings` overriding configurations from previous `useTemplate`, `useStyle`, `useBorder`, `useText`, `useImage` calls.
|
|
102
|
+
* A subsequent `.options()` call overriding configurations set by `useSettings`.
|
|
103
|
+
* `.build()` using the correct configuration when `useSettings` is involved.
|
|
104
|
+
* Interaction with `useImage(..., {override:true})` and `useText(..., {override:true})` when called after `useSettings`.
|
|
105
|
+
|
|
106
|
+
### 3.3. Documentation Updates
|
|
107
|
+
* **[`docs/api-reference-guide.md`](docs/api-reference-guide.md):** Add `useSettings` to the `QRCodeBuilder` methods table.
|
|
108
|
+
* **[`docs/usage-guide.md`](docs/usage-guide.md):** Add a new subsection explaining `QRCodeBuilder.useSettings` with clear examples, emphasizing its override behavior and interaction with `.options()`.
|
|
109
|
+
|
|
110
|
+
## 4. Files to be Modified for Remaining Tasks
|
|
111
|
+
* [`src/index.ts`](src/index.ts) (for `QRCodeBuilder`)
|
|
112
|
+
* [`src/node.ts`](src/node.ts) (for `QRCodeBuilder`)
|
|
113
|
+
* [`tests/node/node.settings.test.ts`](tests/node/node.settings.test.ts) (and potentially new test files)
|
|
114
|
+
* [`docs/api-reference-guide.md`](docs/api-reference-guide.md)
|
|
115
|
+
* [`docs/usage-guide.md`](docs/usage-guide.md)
|
|
116
|
+
|
|
117
|
+
## 5. Key Considerations for `_resolveAndMergeConfig`
|
|
118
|
+
The logic for merging needs to be precise:
|
|
119
|
+
1. If `_settingsSource` is present, it forms the new "base" by applying its constituent parts (template, style, border, text, image, data, options) sequentially on top of `baseQRTemplateOptions`.
|
|
120
|
+
2. If `_settingsSource` is NOT present, the old logic of applying `_initialOptions`, `_templateSource`, etc., applies.
|
|
121
|
+
3. `finalOptions` (from `.options()`) are merged *after* the above, allowing them to override anything set by `useSettings` or other builder methods.
|
|
122
|
+
4. Specific `override: true` calls for `useImage` or `useText` should still function as the ultimate override for those specific properties if they are called *after* `useSettings` (which would have nulled out `_settingsSource` and re-activated `_imageSource`/`_textSource`).
|
|
123
|
+
|
|
124
|
+
This structured plan should allow for a smooth continuation of the task.
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# Feature FT009 - Settings Option Implementation Plan
|
|
2
|
+
|
|
3
|
+
This document outlines the plan to implement the `setSettings()` instance method and the `.settings()` builder method for the `QRCodeJs` class, as per Task ID FT009.
|
|
4
|
+
|
|
5
|
+
## I. Define `SettingsOptions` Type
|
|
6
|
+
|
|
7
|
+
1. **Create/Update Type Definition File:**
|
|
8
|
+
* A new file, `src/types/settings-options.ts`, will be created.
|
|
9
|
+
* **Content:**
|
|
10
|
+
```typescript
|
|
11
|
+
import { RecursivePartial } from './helper';
|
|
12
|
+
import { Options, BorderOptions } from '../utils/options';
|
|
13
|
+
import { StyleOptions } from './style-options';
|
|
14
|
+
import { TextOptions } from './text-options';
|
|
15
|
+
|
|
16
|
+
export interface SettingsOptions {
|
|
17
|
+
id?: string;
|
|
18
|
+
name?: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
template?: string | RecursivePartial<Options>;
|
|
21
|
+
templateId?: string;
|
|
22
|
+
style?: string | StyleOptions;
|
|
23
|
+
styleId?: string;
|
|
24
|
+
text?: string | TextOptions;
|
|
25
|
+
textId?: string;
|
|
26
|
+
border?: string | RecursivePartial<BorderOptions>;
|
|
27
|
+
borderId?: string;
|
|
28
|
+
options?: RecursivePartial<Options>; // For direct overrides/merges into the main Options
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
2. **Export:** Ensure `SettingsOptions` is exported from this new file.
|
|
32
|
+
3. **Import in `qr-code-js.ts`:** Add the necessary import for `SettingsOptions`.
|
|
33
|
+
|
|
34
|
+
## II. Implement Static `QRCodeJs.settings()` Method in `qr-code-js.ts`
|
|
35
|
+
|
|
36
|
+
1. **Add Static Property:**
|
|
37
|
+
```typescript
|
|
38
|
+
private static _selectedSettings: SettingsOptions | null = null;
|
|
39
|
+
```
|
|
40
|
+
2. **Create Static `settings()` Method:**
|
|
41
|
+
* Define the public static method:
|
|
42
|
+
```typescript
|
|
43
|
+
public static settings(settings: SettingsOptions | null): typeof QRCodeJs {
|
|
44
|
+
// 1. Reset all existing static configurations to ensure "replace" behavior
|
|
45
|
+
QRCodeJs._selectedTemplate = null;
|
|
46
|
+
QRCodeJs._selectedBorder = null;
|
|
47
|
+
QRCodeJs._selectedStyle = null;
|
|
48
|
+
QRCodeJs._selectedImage = null;
|
|
49
|
+
QRCodeJs._selectedImageOverride = false;
|
|
50
|
+
QRCodeJs._selectedText = null;
|
|
51
|
+
QRCodeJs._selectedTextOverride = false;
|
|
52
|
+
// Potentially other static states if any are missed here.
|
|
53
|
+
|
|
54
|
+
if (settings === null) {
|
|
55
|
+
QRCodeJs._selectedSettings = null;
|
|
56
|
+
return QRCodeJs;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
QRCodeJs._selectedSettings = settings;
|
|
60
|
+
|
|
61
|
+
// 2. Apply individual configurations from the 'settings' object
|
|
62
|
+
if (settings.templateId) {
|
|
63
|
+
QRCodeJs.setTemplateId(settings.templateId);
|
|
64
|
+
} else if (settings.template) {
|
|
65
|
+
QRCodeJs.setTemplate(settings.template);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (settings.styleId) {
|
|
69
|
+
QRCodeJs.setStyleId(settings.styleId);
|
|
70
|
+
} else if (settings.style) {
|
|
71
|
+
QRCodeJs.setStyle(settings.style);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (settings.textId) {
|
|
75
|
+
QRCodeJs.setTextId(settings.textId);
|
|
76
|
+
} else if (settings.text) {
|
|
77
|
+
QRCodeJs.setText(settings.text);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (settings.borderId) {
|
|
81
|
+
QRCodeJs.setBorderId(settings.borderId);
|
|
82
|
+
} else if (settings.border) {
|
|
83
|
+
QRCodeJs.setBorder(settings.border);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return QRCodeJs;
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## III. Modify `QRCodeJs` Constructor in `qr-code-js.ts`
|
|
91
|
+
|
|
92
|
+
* The constructor's option merging logic needs to account for `_selectedSettings`.
|
|
93
|
+
* **Revised Constructor Logic (Conceptual):**
|
|
94
|
+
1. Initialize `baseOptions`.
|
|
95
|
+
2. Initialize `staticSettingsOptions = {}`.
|
|
96
|
+
3. **If `QRCodeJs._selectedSettings` exists:**
|
|
97
|
+
* If `QRCodeJs._selectedSettings.options` exists, `staticSettingsOptions` is merged with `QRCodeJs._selectedSettings.options`.
|
|
98
|
+
* The presence of `_selectedSettings` implies that `_selectedTemplate`, `_selectedStyle`, etc., would have already been set by the `QRCodeJs.settings()` static method. The existing constructor logic that processes these will pick up the values derived from `_selectedSettings`.
|
|
99
|
+
4. The merging order would be: `baseQRTemplateOptions`, then `staticSettingsOptions` (from `_selectedSettings.options`), then options from `_selectedTemplate`, `_selectedBorder`, `_selectedText`, `_selectedStyle`, `_selectedImage` (if any), and finally `rawOptions` passed to the constructor.
|
|
100
|
+
5. `mergeDeep` will handle the combination.
|
|
101
|
+
6. Proceed with validation and sanitization.
|
|
102
|
+
|
|
103
|
+
## IV. Implement Instance `setSettings()` Method in `qr-code-js.ts`
|
|
104
|
+
|
|
105
|
+
1. **Create Instance `setSettings()` Method:**
|
|
106
|
+
```typescript
|
|
107
|
+
public async setSettings(settings: SettingsOptions): Promise<void> {
|
|
108
|
+
let newOptions: RecursivePartial<Options> = { ...baseQRTemplateOptions }; // Start fresh for "replace"
|
|
109
|
+
|
|
110
|
+
// 1. Apply template
|
|
111
|
+
if (settings.templateId) {
|
|
112
|
+
const foundTemplate = findTemplateById(settings.templateId);
|
|
113
|
+
if (foundTemplate) newOptions = mergeDeep(newOptions, foundTemplate.options);
|
|
114
|
+
} else if (settings.template) {
|
|
115
|
+
if (typeof settings.template === 'string') {
|
|
116
|
+
const foundTemplate = findTemplateByName(settings.template);
|
|
117
|
+
if (foundTemplate) newOptions = mergeDeep(newOptions, foundTemplate.options);
|
|
118
|
+
} else {
|
|
119
|
+
newOptions = mergeDeep(newOptions, settings.template);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 2. Apply style
|
|
124
|
+
if (settings.styleId) {
|
|
125
|
+
const foundStyleDef = findStyleById(settings.styleId);
|
|
126
|
+
if (foundStyleDef) newOptions = mergeDeep(newOptions, mapStyleToOptions(foundStyleDef.style));
|
|
127
|
+
} else if (settings.style) {
|
|
128
|
+
if (typeof settings.style === 'string') {
|
|
129
|
+
const foundStyleDef = findStyleByName(settings.style);
|
|
130
|
+
if (foundStyleDef) newOptions = mergeDeep(newOptions, mapStyleToOptions(foundStyleDef.style));
|
|
131
|
+
} else {
|
|
132
|
+
const { isValid, errors } = validateStyleOptions(settings.style);
|
|
133
|
+
if (isValid) {
|
|
134
|
+
newOptions = mergeDeep(newOptions, mapStyleToOptions(settings.style));
|
|
135
|
+
} else {
|
|
136
|
+
console.warn('Invalid style options in setSettings:', errors);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 3. Apply text
|
|
142
|
+
let textOptionsToApply: RecursivePartial<Options> = {};
|
|
143
|
+
let textOpts: TextOptions | null = null;
|
|
144
|
+
if (settings.textId) {
|
|
145
|
+
const foundTextTemplate = findTextTemplateById(settings.textId);
|
|
146
|
+
if (foundTextTemplate) textOpts = foundTextTemplate.options;
|
|
147
|
+
} else if (settings.text) {
|
|
148
|
+
if (typeof settings.text === 'string') {
|
|
149
|
+
const foundTextTemplate = findTextByName(settings.text);
|
|
150
|
+
if (foundTextTemplate) textOpts = foundTextTemplate.options;
|
|
151
|
+
} else {
|
|
152
|
+
textOpts = settings.text;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (textOpts) {
|
|
156
|
+
// Logic to map textOpts to borderOptions.decorations (similar to constructor)
|
|
157
|
+
if (!textOptionsToApply.borderOptions) textOptionsToApply.borderOptions = {};
|
|
158
|
+
if (!textOptionsToApply.borderOptions.decorations) textOptionsToApply.borderOptions.decorations = {};
|
|
159
|
+
const decorations = textOptionsToApply.borderOptions.decorations;
|
|
160
|
+
// ... (full mapping logic for value, topValue, leftValue, etc.)
|
|
161
|
+
newOptions = mergeDeep(newOptions, textOptionsToApply);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// 4. Apply border
|
|
165
|
+
if (settings.borderId) {
|
|
166
|
+
const foundBorder = findBorderById(settings.borderId);
|
|
167
|
+
if (foundBorder) newOptions = mergeDeep(newOptions, foundBorder.options);
|
|
168
|
+
} else if (settings.border) {
|
|
169
|
+
if (typeof settings.border === 'string') {
|
|
170
|
+
const foundBorder = findBorderByName(settings.border);
|
|
171
|
+
if (foundBorder) newOptions = mergeDeep(newOptions, foundBorder.options);
|
|
172
|
+
} else { // It's RecursivePartial<BorderOptions>
|
|
173
|
+
newOptions = mergeDeep(newOptions, { borderOptions: settings.border });
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// 5. Apply direct options override
|
|
178
|
+
if (settings.options) {
|
|
179
|
+
newOptions = mergeDeep(newOptions, settings.options);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// 6. Validate and sanitize the completely new options
|
|
183
|
+
const { warnings, validatedOptions } = validateQROptions(newOptions);
|
|
184
|
+
if (warnings.length > 0) {
|
|
185
|
+
this._logValidationWarnings('QR Code setSettings Validation Warnings:', warnings);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
this.options = sanitizeOptions(validatedOptions as Options); // Replace current options
|
|
189
|
+
|
|
190
|
+
// 7. Update the QR code
|
|
191
|
+
await this.update();
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## V. Documentation and Tests
|
|
196
|
+
|
|
197
|
+
1. **Documentation:**
|
|
198
|
+
* Add `SettingsOptions` to `docs/typescript-types-definitions.md`.
|
|
199
|
+
* Document `QRCodeJs.settings()` and `instance.setSettings()` in `docs/api-reference-guide.md` and `docs/usage-guide.md`.
|
|
200
|
+
* Clearly explain the "replace" behavior for both methods.
|
|
201
|
+
* Provide usage examples.
|
|
202
|
+
2. **Unit Tests:**
|
|
203
|
+
* Add comprehensive tests for static `settings()`, instance `setSettings()`, their "replace" behavior, and interactions.
|
|
204
|
+
|
|
205
|
+
## Mermaid Diagram
|
|
206
|
+
|
|
207
|
+
```mermaid
|
|
208
|
+
graph TD
|
|
209
|
+
subgraph Initialization
|
|
210
|
+
A[Define SettingsOptions Interface in src/types/settings-options.ts]
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
subgraph Static/Builder Method
|
|
214
|
+
B[Add static _selectedSettings to QRCodeJs]
|
|
215
|
+
C[Implement static QRCodeJs.settings(settings)]
|
|
216
|
+
C --> C1{settings === null?}
|
|
217
|
+
C1 -- Yes --> C2[Reset _selectedSettings AND all other static config (_template, _style, etc.)]
|
|
218
|
+
C1 -- No --> C3[Reset all other static config (_template, _style, etc.)]
|
|
219
|
+
C3 --> C4[Store in _selectedSettings]
|
|
220
|
+
C4 --> C5[Apply settings.template/Id via QRCodeJs.setTemplate/Id]
|
|
221
|
+
C5 --> C6[Apply settings.style/Id via QRCodeJs.setStyle/Id]
|
|
222
|
+
C6 --> C7[Apply settings.text/Id via QRCodeJs.setText/Id]
|
|
223
|
+
C7 --> C8[Apply settings.border/Id via QRCodeJs.setBorder/Id]
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
subgraph Constructor Modification
|
|
227
|
+
D[Modify QRCodeJs Constructor]
|
|
228
|
+
D --> D1[If _selectedSettings exists, its .options form part of the base]
|
|
229
|
+
D --> D2[Existing logic for _selectedTemplate, _selectedStyle, etc. then applies (values may come from _selectedSettings)]
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
subgraph Instance Method
|
|
233
|
+
E[Implement instance.setSettings(settings)]
|
|
234
|
+
E --> E1[Start with newOptions = baseQRTemplateOptions]
|
|
235
|
+
E1 --> E2[Apply settings.template/Id to newOptions (mergeDeep)]
|
|
236
|
+
E2 --> E3[Apply settings.style/Id to newOptions (map & mergeDeep)]
|
|
237
|
+
E3 --> E4[Apply settings.text/Id to newOptions (convert & mergeDeep)]
|
|
238
|
+
E4 --> E5[Apply settings.border/Id to newOptions (mergeDeep)]
|
|
239
|
+
E5 --> E6[Apply settings.options to newOptions (mergeDeep)]
|
|
240
|
+
E6 --> E7[Validate and Sanitize newOptions]
|
|
241
|
+
E7 --> E8[this.options = sanitizedNewOptions (REPLACE)]
|
|
242
|
+
E8 --> E9[Call this.update()]
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
subgraph Documentation & Testing
|
|
246
|
+
F[Update Documentation (Type, Static Method, Instance Method)]
|
|
247
|
+
G[Add Unit Tests (Static, Instance, Interactions, Replace Behavior)]
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
A --> C
|
|
251
|
+
A --> E
|
|
252
|
+
C8 --> D1
|
|
253
|
+
E9 --> G
|
|
254
|
+
F --> G
|
|
@@ -270,6 +270,7 @@ interface DecorationOptions {
|
|
|
270
270
|
fontSize: number;
|
|
271
271
|
fontColor: string;
|
|
272
272
|
letterSpacing: number;
|
|
273
|
+
textTransform: 'uppercase' | 'lowercase' | 'capitalize';
|
|
273
274
|
fontWeight: 'normal' | 'bold';
|
|
274
275
|
};
|
|
275
276
|
}
|
|
@@ -292,6 +293,60 @@ interface Gradient {
|
|
|
292
293
|
}
|
|
293
294
|
```
|
|
294
295
|
|
|
296
|
+
### SettingsOptions
|
|
297
|
+
|
|
298
|
+
Options for configuring multiple aspects of the QR code in a centralized way via `QRCodeJs.settings()` (static) or `instance.setSettings()` (instance).
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
interface SettingsOptions {
|
|
302
|
+
/** Optional ID for the settings preset. */
|
|
303
|
+
id?: string;
|
|
304
|
+
|
|
305
|
+
/** Optional name for the settings preset. */
|
|
306
|
+
name?: string;
|
|
307
|
+
|
|
308
|
+
/** Optional description for the settings preset. */
|
|
309
|
+
description?: string;
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Template to apply. Can be a template name (string) or a
|
|
313
|
+
* `RecursivePartial<Options>` object.
|
|
314
|
+
* This will be applied via `QRCodeJs.setTemplate()` or `QRCodeJs.setTemplateId()`.
|
|
315
|
+
*/
|
|
316
|
+
template?: string | RecursivePartial<Options>;
|
|
317
|
+
templateId?: string;
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Style to apply. Can be a style name (string) or a `StyleOptions` object.
|
|
321
|
+
* This will be applied via `QRCodeJs.setStyle()` or `QRCodeJs.setStyleId()`.
|
|
322
|
+
*/
|
|
323
|
+
style?: string | StyleOptions;
|
|
324
|
+
styleId?: string;
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Text configuration to apply. Can be a text template name (string) or a `TextOptions` object.
|
|
328
|
+
* This will be applied via `QRCodeJs.setText()` or `QRCodeJs.setTextId()`.
|
|
329
|
+
*/
|
|
330
|
+
text?: string | TextOptions;
|
|
331
|
+
textId?: string;
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Border configuration to apply. Can be a border template name (string) or a
|
|
335
|
+
* `RecursivePartial<BorderOptions>` object.
|
|
336
|
+
* This will be applied via `QRCodeJs.setBorder()` or `QRCodeJs.setBorderId()`.
|
|
337
|
+
*/
|
|
338
|
+
border?: string | RecursivePartial<BorderOptions>;
|
|
339
|
+
borderId?: string;
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* A `RecursivePartial<Options>` object that will be deeply merged into
|
|
343
|
+
* the QR code's main options. This allows for direct overrides of any specific
|
|
344
|
+
* properties within the `Options` interface.
|
|
345
|
+
*/
|
|
346
|
+
options?: RecursivePartial<Options>;
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
295
350
|
## Enums
|
|
296
351
|
|
|
297
352
|
These enums provide predefined values for certain properties, ensuring type safety.
|