@willwade/aac-processors 0.0.4 → 0.0.6
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 +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/core/treeStructure.d.ts +9 -1
- package/dist/core/treeStructure.js +5 -1
- package/dist/processors/applePanelsProcessor.js +67 -41
- package/dist/processors/astericsGridProcessor.js +120 -88
- package/dist/processors/excelProcessor.d.ts +3 -3
- package/dist/processors/excelProcessor.js +48 -77
- package/dist/processors/gridset/styleHelpers.d.ts +46 -0
- package/dist/processors/gridset/styleHelpers.js +211 -0
- package/dist/processors/gridset/wordlistHelpers.js +3 -2
- package/dist/processors/gridsetProcessor.js +97 -105
- package/dist/processors/index.d.ts +1 -0
- package/dist/processors/index.js +8 -1
- package/dist/processors/obfProcessor.d.ts +2 -0
- package/dist/processors/obfProcessor.js +129 -52
- package/dist/processors/opmlProcessor.js +13 -3
- package/dist/processors/snapProcessor.js +18 -10
- package/dist/processors/touchchatProcessor.js +45 -22
- package/dist/types/aac.d.ts +4 -0
- package/docs/Grid3-Styling-Guide.md +287 -0
- package/package.json +1 -1
|
@@ -185,7 +185,6 @@ class SnapProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
185
185
|
}
|
|
186
186
|
// Create semantic action for Snap button
|
|
187
187
|
let semanticAction;
|
|
188
|
-
let legacyAction = null;
|
|
189
188
|
if (targetPageUniqueId) {
|
|
190
189
|
semanticAction = {
|
|
191
190
|
category: treeStructure_1.AACSemanticCategory.NAVIGATION,
|
|
@@ -202,10 +201,6 @@ class SnapProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
202
201
|
targetPageId: targetPageUniqueId,
|
|
203
202
|
},
|
|
204
203
|
};
|
|
205
|
-
legacyAction = {
|
|
206
|
-
type: 'NAVIGATE',
|
|
207
|
-
targetPageId: targetPageUniqueId,
|
|
208
|
-
};
|
|
209
204
|
}
|
|
210
205
|
else {
|
|
211
206
|
semanticAction = {
|
|
@@ -283,15 +278,16 @@ class SnapProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
283
278
|
return tree;
|
|
284
279
|
}
|
|
285
280
|
catch (error) {
|
|
281
|
+
const fileIdentifier = typeof filePathOrBuffer === 'string' ? filePathOrBuffer : '[buffer input]';
|
|
286
282
|
// Provide more specific error messages
|
|
287
283
|
if (error.code === 'SQLITE_NOTADB') {
|
|
288
284
|
throw new Error(`Invalid SQLite database file: ${typeof filePathOrBuffer === 'string' ? filePathOrBuffer : 'buffer'}`);
|
|
289
285
|
}
|
|
290
286
|
else if (error.code === 'ENOENT') {
|
|
291
|
-
throw new Error(`File not found: ${
|
|
287
|
+
throw new Error(`File not found: ${fileIdentifier}`);
|
|
292
288
|
}
|
|
293
289
|
else if (error.code === 'EACCES') {
|
|
294
|
-
throw new Error(`Permission denied accessing file: ${
|
|
290
|
+
throw new Error(`Permission denied accessing file: ${fileIdentifier}`);
|
|
295
291
|
}
|
|
296
292
|
else {
|
|
297
293
|
throw new Error(`Failed to load Snap file: ${error.message}`);
|
|
@@ -320,15 +316,24 @@ class SnapProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
320
316
|
Object.values(tree.pages).forEach((page) => {
|
|
321
317
|
// Translate page names
|
|
322
318
|
if (page.name && translations.has(page.name)) {
|
|
323
|
-
|
|
319
|
+
const translatedName = translations.get(page.name);
|
|
320
|
+
if (translatedName !== undefined) {
|
|
321
|
+
page.name = translatedName;
|
|
322
|
+
}
|
|
324
323
|
}
|
|
325
324
|
// Translate button labels and messages
|
|
326
325
|
page.buttons.forEach((button) => {
|
|
327
326
|
if (button.label && translations.has(button.label)) {
|
|
328
|
-
|
|
327
|
+
const translatedLabel = translations.get(button.label);
|
|
328
|
+
if (translatedLabel !== undefined) {
|
|
329
|
+
button.label = translatedLabel;
|
|
330
|
+
}
|
|
329
331
|
}
|
|
330
332
|
if (button.message && translations.has(button.message)) {
|
|
331
|
-
|
|
333
|
+
const translatedMessage = translations.get(button.message);
|
|
334
|
+
if (translatedMessage !== undefined) {
|
|
335
|
+
button.message = translatedMessage;
|
|
336
|
+
}
|
|
332
337
|
}
|
|
333
338
|
});
|
|
334
339
|
});
|
|
@@ -419,6 +424,9 @@ class SnapProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
419
424
|
// Second pass: create buttons with proper page references
|
|
420
425
|
Object.values(tree.pages).forEach((page) => {
|
|
421
426
|
const numericPageId = pageIdMap.get(page.id);
|
|
427
|
+
if (numericPageId === undefined) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
422
430
|
page.buttons.forEach((button, index) => {
|
|
423
431
|
// Find button position in grid layout
|
|
424
432
|
let gridPosition = `${index % 4},${Math.floor(index / 4)}`; // Default fallback
|
|
@@ -12,6 +12,9 @@ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
|
12
12
|
const path_1 = __importDefault(require("path"));
|
|
13
13
|
const fs_1 = __importDefault(require("fs"));
|
|
14
14
|
const os_1 = __importDefault(require("os"));
|
|
15
|
+
const toNumberOrUndefined = (value) => typeof value === 'number' ? value : undefined;
|
|
16
|
+
const toStringOrUndefined = (value) => typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
17
|
+
const toBooleanOrUndefined = (value) => typeof value === 'number' ? value !== 0 : undefined;
|
|
15
18
|
function intToHex(colorInt) {
|
|
16
19
|
if (colorInt === null || typeof colorInt === 'undefined') {
|
|
17
20
|
return undefined;
|
|
@@ -84,7 +87,9 @@ class TouchChatProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
84
87
|
const buttonStyles = new Map();
|
|
85
88
|
const pageStyles = new Map();
|
|
86
89
|
try {
|
|
87
|
-
const buttonStyleRows = db
|
|
90
|
+
const buttonStyleRows = db
|
|
91
|
+
.prepare('SELECT * FROM button_styles')
|
|
92
|
+
.all();
|
|
88
93
|
buttonStyleRows.forEach((style) => {
|
|
89
94
|
buttonStyles.set(style.id, style);
|
|
90
95
|
});
|
|
@@ -162,15 +167,15 @@ class TouchChatProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
162
167
|
style: {
|
|
163
168
|
backgroundColor: intToHex(style?.body_color),
|
|
164
169
|
borderColor: intToHex(style?.border_color),
|
|
165
|
-
borderWidth: style?.border_width,
|
|
170
|
+
borderWidth: toNumberOrUndefined(style?.border_width),
|
|
166
171
|
fontColor: intToHex(style?.font_color),
|
|
167
|
-
fontSize: style?.font_height,
|
|
168
|
-
fontFamily: style?.font_name,
|
|
169
|
-
fontWeight: style?.font_bold ? 'bold' :
|
|
170
|
-
fontStyle: style?.font_italic ? 'italic' :
|
|
171
|
-
textUnderline: style?.font_underline,
|
|
172
|
-
transparent: style?.transparent,
|
|
173
|
-
labelOnTop: style?.label_on_top,
|
|
172
|
+
fontSize: toNumberOrUndefined(style?.font_height),
|
|
173
|
+
fontFamily: toStringOrUndefined(style?.font_name),
|
|
174
|
+
fontWeight: style?.font_bold ? 'bold' : undefined,
|
|
175
|
+
fontStyle: style?.font_italic ? 'italic' : undefined,
|
|
176
|
+
textUnderline: toBooleanOrUndefined(style?.font_underline),
|
|
177
|
+
transparent: toBooleanOrUndefined(style?.transparent),
|
|
178
|
+
labelOnTop: toBooleanOrUndefined(style?.label_on_top),
|
|
174
179
|
},
|
|
175
180
|
});
|
|
176
181
|
buttonBoxes.get(cell.box_id)?.push({
|
|
@@ -276,15 +281,15 @@ class TouchChatProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
276
281
|
style: {
|
|
277
282
|
backgroundColor: intToHex(style?.body_color),
|
|
278
283
|
borderColor: intToHex(style?.border_color),
|
|
279
|
-
borderWidth: style?.border_width,
|
|
284
|
+
borderWidth: toNumberOrUndefined(style?.border_width),
|
|
280
285
|
fontColor: intToHex(style?.font_color),
|
|
281
|
-
fontSize: style?.font_height,
|
|
282
|
-
fontFamily: style?.font_name,
|
|
283
|
-
fontWeight: style?.font_bold ? 'bold' :
|
|
284
|
-
fontStyle: style?.font_italic ? 'italic' :
|
|
285
|
-
textUnderline: style?.font_underline,
|
|
286
|
-
transparent: style?.transparent,
|
|
287
|
-
labelOnTop: style?.label_on_top,
|
|
286
|
+
fontSize: toNumberOrUndefined(style?.font_height),
|
|
287
|
+
fontFamily: toStringOrUndefined(style?.font_name),
|
|
288
|
+
fontWeight: style?.font_bold ? 'bold' : undefined,
|
|
289
|
+
fontStyle: style?.font_italic ? 'italic' : undefined,
|
|
290
|
+
textUnderline: toBooleanOrUndefined(style?.font_underline),
|
|
291
|
+
transparent: toBooleanOrUndefined(style?.transparent),
|
|
292
|
+
labelOnTop: toBooleanOrUndefined(style?.label_on_top),
|
|
288
293
|
},
|
|
289
294
|
});
|
|
290
295
|
// Find the page that references this resource
|
|
@@ -380,15 +385,24 @@ class TouchChatProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
380
385
|
Object.values(tree.pages).forEach((page) => {
|
|
381
386
|
// Translate page names
|
|
382
387
|
if (page.name && translations.has(page.name)) {
|
|
383
|
-
|
|
388
|
+
const translatedName = translations.get(page.name);
|
|
389
|
+
if (translatedName !== undefined) {
|
|
390
|
+
page.name = translatedName;
|
|
391
|
+
}
|
|
384
392
|
}
|
|
385
393
|
// Translate button labels and messages
|
|
386
394
|
page.buttons.forEach((button) => {
|
|
387
395
|
if (button.label && translations.has(button.label)) {
|
|
388
|
-
|
|
396
|
+
const translatedLabel = translations.get(button.label);
|
|
397
|
+
if (translatedLabel !== undefined) {
|
|
398
|
+
button.label = translatedLabel;
|
|
399
|
+
}
|
|
389
400
|
}
|
|
390
401
|
if (button.message && translations.has(button.message)) {
|
|
391
|
-
|
|
402
|
+
const translatedMessage = translations.get(button.message);
|
|
403
|
+
if (translatedMessage !== undefined) {
|
|
404
|
+
button.message = translatedMessage;
|
|
405
|
+
}
|
|
392
406
|
}
|
|
393
407
|
});
|
|
394
408
|
});
|
|
@@ -560,7 +574,10 @@ class TouchChatProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
560
574
|
insertPageStyle.run(pageStyleId, hexToInt(page.style.backgroundColor), page.style.backgroundColor ? 1 : 0);
|
|
561
575
|
}
|
|
562
576
|
else {
|
|
563
|
-
|
|
577
|
+
const existingPageStyleId = pageStyleMap.get(styleKey);
|
|
578
|
+
if (typeof existingPageStyleId === 'number') {
|
|
579
|
+
pageStyleId = existingPageStyleId;
|
|
580
|
+
}
|
|
564
581
|
}
|
|
565
582
|
}
|
|
566
583
|
// Insert resource for page name
|
|
@@ -577,6 +594,9 @@ class TouchChatProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
577
594
|
// Second pass: create buttons and their relationships
|
|
578
595
|
Object.values(tree.pages).forEach((page) => {
|
|
579
596
|
const numericPageId = pageIdMap.get(page.id);
|
|
597
|
+
if (numericPageId === undefined) {
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
580
600
|
if (page.buttons.length > 0) {
|
|
581
601
|
// Calculate grid dimensions from page.grid or use fallback
|
|
582
602
|
let gridWidth = 4; // Default fallback
|
|
@@ -631,7 +651,10 @@ class TouchChatProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
631
651
|
insertButtonStyle.run(buttonStyleId, button.style.labelOnTop ? 1 : 0, button.style.transparent ? 1 : 0, hexToInt(button.style.fontColor), hexToInt(button.style.backgroundColor), hexToInt(button.style.borderColor), button.style.borderWidth, button.style.fontFamily, button.style.fontWeight === 'bold' ? 1 : 0, button.style.textUnderline ? 1 : 0, button.style.fontStyle === 'italic' ? 1 : 0, button.style.fontSize);
|
|
632
652
|
}
|
|
633
653
|
else {
|
|
634
|
-
|
|
654
|
+
const existingButtonStyleId = buttonStyleMap.get(styleKey);
|
|
655
|
+
if (typeof existingButtonStyleId === 'number') {
|
|
656
|
+
buttonStyleId = existingButtonStyleId;
|
|
657
|
+
}
|
|
635
658
|
}
|
|
636
659
|
}
|
|
637
660
|
if (!insertedButtonIds.has(numericButtonId)) {
|
package/dist/types/aac.d.ts
CHANGED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# Grid3 Styling Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how to work with Grid3 styles using the AACProcessors library.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Grid3 uses a sophisticated styling system with:
|
|
8
|
+
- **Default styles** for common UI elements
|
|
9
|
+
- **Category styles** for organizing content by semantic meaning
|
|
10
|
+
- **Inline style overrides** for cell-specific customization
|
|
11
|
+
- **Style inheritance** through `BasedOnStyle` references
|
|
12
|
+
|
|
13
|
+
## Default Styles
|
|
14
|
+
|
|
15
|
+
The library provides built-in default styles for common use cases:
|
|
16
|
+
|
|
17
|
+
### Available Default Styles
|
|
18
|
+
|
|
19
|
+
| Style Name | Purpose | Background | Text Color |
|
|
20
|
+
|-----------|---------|-----------|-----------|
|
|
21
|
+
| `Default` | General purpose cells | Light blue (#E2EDF8) | Black |
|
|
22
|
+
| `Workspace` | Message/chat area | White (#FFFFFF) | Black |
|
|
23
|
+
| `Auto content` | Wordlists, predictions | Light blue (#E8F4F8) | Black |
|
|
24
|
+
| `Vocab cell` | Vocabulary cells | Light blue (#E8F4F8) | Black |
|
|
25
|
+
| `Keyboard key` | On-screen keyboard | Light gray (#F0F0F0) | Black |
|
|
26
|
+
|
|
27
|
+
### Category Styles
|
|
28
|
+
|
|
29
|
+
Category styles are used for organizing content by semantic meaning:
|
|
30
|
+
|
|
31
|
+
| Style Name | Color | Use Case |
|
|
32
|
+
|-----------|-------|----------|
|
|
33
|
+
| `Actions category style` | Blue (#4472C4) | Action verbs, commands |
|
|
34
|
+
| `People category style` | Orange (#ED7D31) | Names, people |
|
|
35
|
+
| `Places category style` | Gray (#A5A5A5) | Locations, places |
|
|
36
|
+
| `Descriptive category style` | Green (#70AD47) | Adjectives, descriptors |
|
|
37
|
+
| `Social category style` | Gold (#FFC000) | Social phrases, greetings |
|
|
38
|
+
| `Questions category style` | Light blue (#5B9BD5) | Questions, interrogatives |
|
|
39
|
+
| `Little words category style` | Brown (#C55A11) | Function words, particles |
|
|
40
|
+
|
|
41
|
+
## Using Styles in Code
|
|
42
|
+
|
|
43
|
+
### Import Style Helpers
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import {
|
|
47
|
+
DEFAULT_GRID3_STYLES,
|
|
48
|
+
CATEGORY_STYLES,
|
|
49
|
+
createDefaultStylesXml,
|
|
50
|
+
createCategoryStyle,
|
|
51
|
+
ensureAlphaChannel,
|
|
52
|
+
} from 'aac-processors';
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Access Predefined Styles
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// Get a specific default style
|
|
59
|
+
const defaultStyle = DEFAULT_GRID3_STYLES['Default'];
|
|
60
|
+
console.log(defaultStyle.BackColour); // #E2EDF8FF
|
|
61
|
+
|
|
62
|
+
// Get a category style
|
|
63
|
+
const actionStyle = CATEGORY_STYLES['Actions category style'];
|
|
64
|
+
console.log(actionStyle.BackColour); // #4472C4FF
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Create Custom Category Styles
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// Create a custom category style with automatic border darkening
|
|
71
|
+
const customStyle = createCategoryStyle(
|
|
72
|
+
'My Category',
|
|
73
|
+
'#FF6B6B', // Background color
|
|
74
|
+
'#FFFFFF' // Font color (optional, defaults to white)
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// Result:
|
|
78
|
+
// {
|
|
79
|
+
// BackColour: '#FF6B6BFF',
|
|
80
|
+
// TileColour: '#FF6B6BFF',
|
|
81
|
+
// BorderColour: '#CB5555FF', // Automatically darkened
|
|
82
|
+
// FontColour: '#FFFFFFFF',
|
|
83
|
+
// FontName: 'Arial',
|
|
84
|
+
// FontSize: '16'
|
|
85
|
+
// }
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Generate Default Styles XML
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
// Generate Settings0/styles.xml with all default and category styles
|
|
92
|
+
const stylesXml = createDefaultStylesXml(true);
|
|
93
|
+
|
|
94
|
+
// Or just default styles without categories
|
|
95
|
+
const basicStylesXml = createDefaultStylesXml(false);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Ensure Color Has Alpha Channel
|
|
99
|
+
|
|
100
|
+
Grid3 requires colors in 8-digit ARGB format (#AARRGGBBFF):
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { ensureAlphaChannel } from 'aac-processors';
|
|
104
|
+
|
|
105
|
+
ensureAlphaChannel('#FF0000'); // Returns: #FF0000FF
|
|
106
|
+
ensureAlphaChannel('#F00'); // Returns: #FF0000FF
|
|
107
|
+
ensureAlphaChannel('#FF0000FF'); // Returns: #FF0000FF (unchanged)
|
|
108
|
+
ensureAlphaChannel(undefined); // Returns: #FFFFFFFF (white)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Applying Styles to Cells
|
|
112
|
+
|
|
113
|
+
### Using BasedOnStyle Reference
|
|
114
|
+
|
|
115
|
+
In Grid3 XML, cells reference styles by name:
|
|
116
|
+
|
|
117
|
+
```xml
|
|
118
|
+
<Cell X="0" Y="0">
|
|
119
|
+
<Content>
|
|
120
|
+
<CaptionAndImage>
|
|
121
|
+
<Caption>Hello</Caption>
|
|
122
|
+
</CaptionAndImage>
|
|
123
|
+
<Style>
|
|
124
|
+
<BasedOnStyle>Actions category style</BasedOnStyle>
|
|
125
|
+
</Style>
|
|
126
|
+
</Content>
|
|
127
|
+
</Cell>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Inline Style Overrides
|
|
131
|
+
|
|
132
|
+
You can override specific properties while keeping the base style:
|
|
133
|
+
|
|
134
|
+
```xml
|
|
135
|
+
<Cell X="1" Y="0">
|
|
136
|
+
<Content>
|
|
137
|
+
<CaptionAndImage>
|
|
138
|
+
<Caption>Custom</Caption>
|
|
139
|
+
</CaptionAndImage>
|
|
140
|
+
<Style>
|
|
141
|
+
<BasedOnStyle>Default</BasedOnStyle>
|
|
142
|
+
<BackColour>#FF0000FF</BackColour> <!-- Override background -->
|
|
143
|
+
<FontSize>20</FontSize> <!-- Override font size -->
|
|
144
|
+
</Style>
|
|
145
|
+
</Content>
|
|
146
|
+
</Cell>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Color Format
|
|
150
|
+
|
|
151
|
+
Grid3 uses 8-digit ARGB hexadecimal format: `#AARRGGBBFF`
|
|
152
|
+
|
|
153
|
+
- **AA**: Alpha channel (FF = fully opaque, 00 = fully transparent)
|
|
154
|
+
- **RR**: Red component (00-FF)
|
|
155
|
+
- **GG**: Green component (00-FF)
|
|
156
|
+
- **BB**: Blue component (00-FF)
|
|
157
|
+
- **FF**: Always FF for Grid3 (fully opaque)
|
|
158
|
+
|
|
159
|
+
### Examples
|
|
160
|
+
|
|
161
|
+
| Color | Hex Code | Description |
|
|
162
|
+
|-------|----------|-------------|
|
|
163
|
+
| White | #FFFFFFFF | Fully opaque white |
|
|
164
|
+
| Black | #000000FF | Fully opaque black |
|
|
165
|
+
| Red | #FF0000FF | Fully opaque red |
|
|
166
|
+
| Blue | #0000FFFF | Fully opaque blue |
|
|
167
|
+
| Green | #00FF00FF | Fully opaque green |
|
|
168
|
+
|
|
169
|
+
## Style Inheritance
|
|
170
|
+
|
|
171
|
+
Grid3 uses a cascading style system:
|
|
172
|
+
|
|
173
|
+
1. **Theme** provides base properties (Modern, Kids/Bubble, Flat/Blocky, Explorer)
|
|
174
|
+
2. **Built-in style** defines category defaults
|
|
175
|
+
3. **Cell-specific overrides** apply on top
|
|
176
|
+
|
|
177
|
+
```xml
|
|
178
|
+
<!-- Example: Override just the background color -->
|
|
179
|
+
<Style>
|
|
180
|
+
<BasedOnStyle>Actions category style</BasedOnStyle>
|
|
181
|
+
<BackColour>#FF0000FF</BackColour> <!-- Override just this property -->
|
|
182
|
+
</Style>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Creating Gridsets with Styles
|
|
186
|
+
|
|
187
|
+
### Using GridsetProcessor
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import { GridsetProcessor, AACTree, AACPage, AACButton } from 'aac-processors';
|
|
191
|
+
|
|
192
|
+
const processor = new GridsetProcessor();
|
|
193
|
+
const tree = new AACTree();
|
|
194
|
+
|
|
195
|
+
// Create a page with styling
|
|
196
|
+
const page = new AACPage({
|
|
197
|
+
id: 'main-page',
|
|
198
|
+
name: 'Main Board',
|
|
199
|
+
grid: [],
|
|
200
|
+
buttons: [],
|
|
201
|
+
parentId: null,
|
|
202
|
+
style: {
|
|
203
|
+
backgroundColor: '#f0f8ff',
|
|
204
|
+
fontFamily: 'Arial',
|
|
205
|
+
fontSize: 16,
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Create styled buttons
|
|
210
|
+
const button = new AACButton({
|
|
211
|
+
id: 'btn-1',
|
|
212
|
+
label: 'Hello',
|
|
213
|
+
message: 'Hello, how are you?',
|
|
214
|
+
style: {
|
|
215
|
+
backgroundColor: '#4472C4', // Blue (Actions category)
|
|
216
|
+
fontColor: '#FFFFFF',
|
|
217
|
+
fontSize: 18,
|
|
218
|
+
fontFamily: 'Arial',
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
page.addButton(button);
|
|
223
|
+
tree.addPage(page);
|
|
224
|
+
|
|
225
|
+
// Save with styles
|
|
226
|
+
processor.saveFromTree(tree, 'output.gridset');
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Using Grid-Generator
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
import { generateGridset } from '@willwade/grid-generator';
|
|
233
|
+
|
|
234
|
+
const template = {
|
|
235
|
+
aacsystem: 'Grid3',
|
|
236
|
+
homeGrid: {
|
|
237
|
+
enabled: true,
|
|
238
|
+
name: 'Home',
|
|
239
|
+
title: 'Categories',
|
|
240
|
+
},
|
|
241
|
+
wordlists: [
|
|
242
|
+
{
|
|
243
|
+
name: 'Greetings',
|
|
244
|
+
items: ['Hello', 'Hi', 'Hey'],
|
|
245
|
+
partOfSpeech: 'Interjection',
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const gridset = generateGridset(template);
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Best Practices
|
|
254
|
+
|
|
255
|
+
1. **Use category styles** for semantic organization - helps with accessibility and consistency
|
|
256
|
+
2. **Maintain contrast** - ensure text color has sufficient contrast with background
|
|
257
|
+
3. **Use consistent fonts** - stick to standard fonts like Arial, Verdana, or Roboto
|
|
258
|
+
4. **Test in Grid3** - always verify styling in the actual Grid3 application
|
|
259
|
+
5. **Document custom styles** - if creating custom category styles, document their purpose
|
|
260
|
+
6. **Use inline overrides sparingly** - prefer creating new styles for significant variations
|
|
261
|
+
|
|
262
|
+
## Troubleshooting
|
|
263
|
+
|
|
264
|
+
### Styles Not Appearing
|
|
265
|
+
|
|
266
|
+
- Verify `Settings0/styles.xml` exists in the gridset
|
|
267
|
+
- Check that style names in cells match exactly (case-sensitive)
|
|
268
|
+
- Ensure colors are in 8-digit ARGB format
|
|
269
|
+
|
|
270
|
+
### Colors Look Wrong
|
|
271
|
+
|
|
272
|
+
- Verify alpha channel is FF (fully opaque)
|
|
273
|
+
- Check RGB values are correct
|
|
274
|
+
- Test in Grid3 to see actual rendering
|
|
275
|
+
|
|
276
|
+
### Performance Issues
|
|
277
|
+
|
|
278
|
+
- Avoid creating too many unique styles (consolidate similar styles)
|
|
279
|
+
- Use style references instead of inline overrides when possible
|
|
280
|
+
- Keep font sizes reasonable (12-24 points typical)
|
|
281
|
+
|
|
282
|
+
## See Also
|
|
283
|
+
|
|
284
|
+
- [Grid3 XML Format Documentation](./Grid3-XML-Format.md)
|
|
285
|
+
- [Wordlist Helpers Guide](./Grid3-Wordlist-Helpers.md)
|
|
286
|
+
- [AACProcessors API Reference](./API-Reference.md)
|
|
287
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@willwade/aac-processors",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "A comprehensive TypeScript library for processing AAC (Augmentative and Alternative Communication) file formats with translation support",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|