also looking at this
chore(deps): update dependency react-dom to 19.2.7
#2138
222 files
+16350
-1825
Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.
| @@ -2,8 +2,125 @@ | ||
| 2 | 2 | import { barcode } from '@stacksjs/qrx' |
| 3 | 3 | import { nextTick, onMounted, ref, watch } from 'vue' |
| 4 | 4 | |
| 5 | interface BarcodeFormat { | |
| 6 | value: string | |
| 7 | label: string | |
| 8 | pattern: RegExp | |
| 9 | hint: string | |
| 10 | example: string | |
| 11 | } | |
| 12 | ||
| 13 | const formats: BarcodeFormat[] = [ | |
| 14 | { | |
| 15 | value: 'CODE128', | |
| 16 | label: 'Code 128', | |
| 17 | pattern: /^[\x00-\x7F\xC8-\xD3]+$/, | |
| 18 | hint: 'Accepts any ASCII character', | |
| 19 | example: '123ABC', | |
| 20 | }, | |
| 21 | { | |
| 22 | value: 'EAN13', | |
| 23 | label: 'EAN-13', | |
| 24 | pattern: /^\d{12,13}$/, | |
| 25 | hint: 'Must be exactly 12 or 13 digits', | |
| 26 | example: '5901234123457', | |
| 27 | }, | |
| 28 | { | |
| 29 | value: 'EAN8', | |
| 30 | label: 'EAN-8', | |
| 31 | pattern: /^\d{7,8}$/, | |
| 32 | hint: 'Must be exactly 7 or 8 digits', | |
| 33 | example: '96385074', | |
| 34 | }, | |
| 35 | { | |
| 36 | value: 'EAN5', | |
| 37 | label: 'EAN-5', | |
| 38 | pattern: /^\d{5}$/, | |
| 39 | hint: 'Must be exactly 5 digits', | |
| 40 | example: '54495', | |
| 41 | }, | |
| 42 | { | |
| 43 | value: 'EAN2', | |
| 44 | label: 'EAN-2', | |
| 45 | pattern: /^\d{2}$/, | |
| 46 | hint: 'Must be exactly 2 digits', | |
| 47 | example: '53', | |
| 48 | }, | |
| 49 | { | |
| 50 | value: 'UPC', | |
| 51 | label: 'UPC', | |
| 52 | pattern: /^\d{11,12}$/, | |
| 53 | hint: 'Must be exactly 11 or 12 digits', | |
| 54 | example: '123456789012', | |
| 55 | }, | |
| 56 | { | |
| 57 | value: 'CODE39', | |
| 58 | label: 'Code 39', | |
| 59 | pattern: /^[0-9A-Z\-. $/+%]+$/, | |
| 60 | hint: 'Accepts digits, uppercase letters, and special characters: -. $/+%', | |
| 61 | example: 'CODE-39', | |
| 62 | }, | |
| 63 | { | |
| 64 | value: 'ITF14', | |
| 65 | label: 'ITF-14', | |
| 66 | pattern: /^\d{13,14}$/, | |
| 67 | hint: 'Must be exactly 13 or 14 digits', | |
| 68 | example: '15400141288763', | |
| 69 | }, | |
| 70 | { | |
| 71 | value: 'MSI', | |
| 72 | label: 'MSI', | |
| 73 | pattern: /^\d+$/, | |
| 74 | hint: 'Accepts only digits', | |
| 75 | example: '123456', | |
| 76 | }, | |
| 77 | { | |
| 78 | value: 'MSI10', | |
| 79 | label: 'MSI-10', | |
| 80 | pattern: /^\d+$/, | |
| 81 | hint: 'Accepts only digits', | |
| 82 | example: '123456', | |
| 83 | }, | |
| 84 | { | |
| 85 | value: 'MSI11', | |
| 86 | label: 'MSI-11', | |
| 87 | pattern: /^\d+$/, | |
| 88 | hint: 'Accepts only digits', | |
| 89 | example: '123456', | |
| 90 | }, | |
| 91 | { | |
| 92 | value: 'MSI1010', | |
| 93 | label: 'MSI-1010', | |
| 94 | pattern: /^\d+$/, | |
| 95 | hint: 'Accepts only digits', | |
| 96 | example: '123456', | |
| 97 | }, | |
| 98 | { | |
| 99 | value: 'MSI1110', | |
| 100 | label: 'MSI-1110', | |
| 101 | pattern: /^\d+$/, | |
| 102 | hint: 'Accepts only digits', | |
| 103 | example: '123456', | |
| 104 | }, | |
| 105 | { | |
| 106 | value: 'pharmacode', | |
| 107 | label: 'Pharmacode', | |
| 108 | pattern: /^\d+$/, | |
| 109 | hint: 'Must be a number between 3 and 131070', | |
| 110 | example: '1234', | |
| 111 | }, | |
| 112 | { | |
| 113 | value: 'codabar', | |
| 114 | label: 'Codabar', | |
| 115 | pattern: /^[A-D][0-9\-$:/.+]+[A-D]$/, | |
| 116 | hint: 'Must start and end with A-D, content can be digits and -$:/.+', | |
| 117 | example: 'A12345B', | |
| 118 | }, | |
| 119 | ] | |
| 120 | ||
| 5 | 121 | const error = ref('') |
| 6 | const text = ref('123456789') | |
| 122 | const currentFormat = ref(formats[0]) | |
| 123 | const text = ref(formats[0].example) | |
| 7 | 124 | const format = ref('CODE128') |
| 8 | 125 | const width = ref(2) |
| 9 | 126 | const height = ref(100) |
| @@ -18,25 +135,30 @@ const background = ref('#ffffff') | ||
| 18 | 135 | const lineColor = ref('#ffffff') |
| 19 | 136 | const margin = ref(10) |
| 20 | 137 | |
| 138 | watch(format, (newFormat) => { | |
| 139 | currentFormat.value = formats.find(f => f.value === newFormat) || formats[0] | |
| 140 | // Don't automatically change the text when format changes | |
| 141 | }) | |
| 142 | ||
| 21 | 143 | const barcodeContainer = ref<HTMLElement | null>(null) |
| 22 | 144 | |
| 23 | const formats = [ | |
| 24 | 'CODE128', | |
| 25 | 'EAN13', | |
| 26 | 'EAN8', | |
| 27 | 'EAN5', | |
| 28 | 'EAN2', | |
| 29 | 'UPC', | |
| 30 | 'CODE39', | |
| 31 | 'ITF14', | |
| 32 | 'MSI', | |
| 33 | 'MSI10', | |
| 34 | 'MSI11', | |
| 35 | 'MSI1010', | |
| 36 | 'MSI1110', | |
| 37 | 'pharmacode', | |
| 38 | 'codabar', | |
| 39 | ] | |
| 145 | function validateInput(): boolean { | |
| 146 | const format = currentFormat.value | |
| 147 | if (!format.pattern.test(text.value)) { | |
| 148 | error.value = `Invalid format for ${format.label}. ${format.hint}` | |
| 149 | return false | |
| 150 | } | |
| 151 | ||
| 152 | if (format.value === 'pharmacode') { | |
| 153 | const num = Number(text.value) | |
| 154 | if (num < 3 || num > 131070) { | |
| 155 | error.value = 'Pharmacode must be a number between 3 and 131070' | |
| 156 | return false | |
| 157 | } | |
| 158 | } | |
| 159 | ||
| 160 | return true | |
| 161 | } | |
| 40 | 162 | |
| 41 | 163 | function updateBarcode() { |
| 42 | 164 | if (!barcodeContainer.value) |
| @@ -44,6 +166,10 @@ function updateBarcode() { | ||
| 44 | 166 | |
| 45 | 167 | error.value = '' |
| 46 | 168 | |
| 169 | if (!validateInput()) { | |
| 170 | return | |
| 171 | } | |
| 172 | ||
| 47 | 173 | try { |
| 48 | 174 | // Create SVG element inside container |
| 49 | 175 | const svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg') |
| @@ -129,12 +255,18 @@ watch([ | ||
| 129 | 255 | > |
| 130 | 256 | <option |
| 131 | 257 | v-for="fmt in formats" |
| 132 | :key="fmt" | |
| 133 | :value="fmt" | |
| 258 | :key="fmt.value" | |
| 259 | :value="fmt.value" | |
| 134 | 260 | > |
| 135 | {{ fmt }} | |
| 261 | {{ fmt.label }} | |
| 136 | 262 | </option> |
| 137 | 263 | </select> |
| 264 | <div class="format-hint"> | |
| 265 | <p>{{ currentFormat.hint }}</p> | |
| 266 | <p class="example"> | |
| 267 | Example: {{ currentFormat.example }} | |
| 268 | </p> | |
| 269 | </div> | |
| 138 | 270 | </div> |
| 139 | 271 | |
| 140 | 272 | <!-- Display Value Toggle --> |
| @@ -338,6 +470,18 @@ input[type="checkbox"] { | ||
| 338 | 470 | position: relative; |
| 339 | 471 | } |
| 340 | 472 | |
| 473 | .format-hint { | |
| 474 | margin-top: 4px; | |
| 475 | font-size: 0.875rem; | |
| 476 | color: #666; | |
| 477 | } | |
| 478 | ||
| 479 | .format-hint .example { | |
| 480 | color: #0066cc; | |
| 481 | margin-top: 2px; | |
| 482 | font-family: monospace; | |
| 483 | } | |
| 484 | ||
| 341 | 485 | .error-message { |
| 342 | 486 | color: #dc2626; |
| 343 | 487 | margin-bottom: 15px; |