feat: integrate thermal printer functionality with receipt encoding
- Added @point-of-sale/receipt-printer-encoder dependency to package.json. - Implemented useThermalPrinter hook for managing Bluetooth and USB printer connections. - Created encodeOrderReceipt function to format receipt data for printing. - Enhanced TransactionIndex component to include printer connection options and receipt printing functionality. - Added dropdown menu for selecting printer connection type (Bluetooth/USB) and printing receipt options (58mm/80mm). - Updated TransactionCardRow to include print receipt actions. - Defined TypeScript types for receipt printer encoder and web Bluetooth/USB APIs. - Configured Vite to optimize dependencies for receipt printer encoder.
This commit is contained in:
parent
add157183b
commit
f7a91739f9
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Settings\SystemSettings;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Inertia\Middleware;
|
use Inertia\Middleware;
|
||||||
|
|
||||||
@ -38,6 +39,7 @@ public function share(Request $request): array
|
|||||||
return [
|
return [
|
||||||
...parent::share($request),
|
...parent::share($request),
|
||||||
'name' => config('app.name'),
|
'name' => config('app.name'),
|
||||||
|
'address' => app(SystemSettings::class)->address ?? '',
|
||||||
'auth' => [
|
'auth' => [
|
||||||
'user' => $request->user()
|
'user' => $request->user()
|
||||||
? tap($request->user()->load('userProfile', 'roles'), function ($user) {
|
? tap($request->user()->load('userProfile', 'roles'), function ($user) {
|
||||||
|
|||||||
829
package-lock.json
generated
829
package-lock.json
generated
@ -13,6 +13,7 @@
|
|||||||
"@inertiajs/react": "^3.0.0",
|
"@inertiajs/react": "^3.0.0",
|
||||||
"@inertiajs/vite": "^3.0.0",
|
"@inertiajs/vite": "^3.0.0",
|
||||||
"@laravel/passkeys": "^0.2.0",
|
"@laravel/passkeys": "^0.2.0",
|
||||||
|
"@point-of-sale/receipt-printer-encoder": "^3.0.3",
|
||||||
"@radix-ui/react-avatar": "^1.1.3",
|
"@radix-ui/react-avatar": "^1.1.3",
|
||||||
"@radix-ui/react-checkbox": "^1.1.4",
|
"@radix-ui/react-checkbox": "^1.1.4",
|
||||||
"@radix-ui/react-collapsible": "^1.1.3",
|
"@radix-ui/react-collapsible": "^1.1.3",
|
||||||
@ -1779,6 +1780,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@canvas/image-data": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@canvas/image-data/-/image-data-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-QdObRRjRbcXGmM1tmJ+MrHcaz1MftF2+W7YI+MsphnsCrmtyfS0d5qJbk0MeSbUeyM/jCb0hmnkXPsy026L7dA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@date-fns/tz": {
|
"node_modules/@date-fns/tz": {
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@date-fns/tz/-/tz-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@date-fns/tz/-/tz-1.5.0.tgz",
|
||||||
@ -2043,37 +2050,6 @@
|
|||||||
"integrity": "sha512-VYJy0uhFm9zTJ1TxBaW/pA8bjbOM/OttaNMwZ1RHG4JKyRG7DhSdiqD1ipQoAyoD22olUtxbP78W9xY3Wd11bg==",
|
"integrity": "sha512-VYJy0uhFm9zTJ1TxBaW/pA8bjbOM/OttaNMwZ1RHG4JKyRG7DhSdiqD1ipQoAyoD22olUtxbP78W9xY3Wd11bg==",
|
||||||
"license": "BSD-3-Clause"
|
"license": "BSD-3-Clause"
|
||||||
},
|
},
|
||||||
"node_modules/@emnapi/core": {
|
|
||||||
"version": "2.0.0-alpha.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-2.0.0-alpha.3.tgz",
|
|
||||||
"integrity": "sha512-AZypUeJ/yByuxyS7BlSNRDOMLMlROYtjYdIAuBmJssVz1UJDSeYxLrdizhXCFYhedC5bqd/ASy8EuNXbVVXp9g==",
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@emnapi/wasi-threads": "2.0.1",
|
|
||||||
"tslib": "^2.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@emnapi/runtime": {
|
|
||||||
"version": "2.0.0-alpha.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-2.0.0-alpha.3.tgz",
|
|
||||||
"integrity": "sha512-hFPAhMUjJD9BSyCANEISPOogeXC9Zo9ZQl7L6vKnaVsMkCtzznaW/naYypeyl0Gv5rYfWYsZbpixTMpjDJzQeA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": "^2.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@emnapi/wasi-threads": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-9DsSk+o5NBX0CCJT8s0EROGSGxjR/tKu6aBTaVyq+SjAEQH4XcdcRxPBRzsBLizTTJ49MJjF+jgu3qnO9GLQcQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": "^2.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@eslint-community/eslint-utils": {
|
"node_modules/@eslint-community/eslint-utils": {
|
||||||
"version": "4.10.1",
|
"version": "4.10.1",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz",
|
||||||
@ -2583,27 +2559,6 @@
|
|||||||
"node": "^22.20 || ^24.12 || >=25"
|
"node": "^22.20 || ^24.12 || >=25"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@napi-rs/wasm-runtime": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-kDoONqMa+VnZ4vvvu/ZUurpJ4gkZU57e7g69qpNgWhYcZFPUHZM2CEMKm+cG6ufDVALbjMvfmMjFVqaK7uEMnA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@tybys/wasm-util": "^0.10.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^20.19.0 || ^22.13.0 || >=23.5.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/Brooooooklyn"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@emnapi/core": "^2.0.0-alpha.3",
|
|
||||||
"@emnapi/runtime": "^2.0.0-alpha.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@nodelib/fs.scandir": {
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@ -2648,6 +2603,25 @@
|
|||||||
"url": "https://github.com/sponsors/Boshen"
|
"url": "https://github.com/sponsors/Boshen"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@point-of-sale/codepage-encoder": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@point-of-sale/codepage-encoder/-/codepage-encoder-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-Sx+0sE/XgPtMUNKScHpwTIZiHNd/+Mg0udACQJVwPsxH9kUAgIkRi9kRlmWBMCruwOJadjKLyKs8MO8Bh+VS/A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@point-of-sale/receipt-printer-encoder": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@point-of-sale/receipt-printer-encoder/-/receipt-printer-encoder-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-2+xgs6rwNfrkEw9g4LkgQS6k29qnmo3+hOV7Z2xHNBFn8h4FrwquZwL/dBOTwgmQ9sWEYBkj/bQkg9Rz6lL99w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@canvas/image-data": "^1.0.0",
|
||||||
|
"@point-of-sale/codepage-encoder": "^3.0.0",
|
||||||
|
"canvas-dither": "^1.0.1",
|
||||||
|
"canvas-flatten": "^1.0.1",
|
||||||
|
"resize-image-data": "^0.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/number": {
|
"node_modules/@radix-ui/number": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.3.tgz",
|
||||||
@ -4170,150 +4144,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-android-arm64": {
|
|
||||||
"version": "1.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz",
|
|
||||||
"integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"android"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": "^20.19.0 || >=22.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/binding-darwin-arm64": {
|
|
||||||
"version": "1.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz",
|
|
||||||
"integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": "^20.19.0 || >=22.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/binding-darwin-x64": {
|
|
||||||
"version": "1.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz",
|
|
||||||
"integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": "^20.19.0 || >=22.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/binding-freebsd-x64": {
|
|
||||||
"version": "1.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz",
|
|
||||||
"integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"freebsd"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": "^20.19.0 || >=22.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
|
|
||||||
"version": "1.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz",
|
|
||||||
"integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": "^20.19.0 || >=22.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/binding-linux-arm64-gnu": {
|
|
||||||
"version": "1.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz",
|
|
||||||
"integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": "^20.19.0 || >=22.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/binding-linux-arm64-musl": {
|
|
||||||
"version": "1.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz",
|
|
||||||
"integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": "^20.19.0 || >=22.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
|
|
||||||
"version": "1.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz",
|
|
||||||
"integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==",
|
|
||||||
"cpu": [
|
|
||||||
"ppc64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": "^20.19.0 || >=22.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/binding-linux-s390x-gnu": {
|
|
||||||
"version": "1.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz",
|
|
||||||
"integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==",
|
|
||||||
"cpu": [
|
|
||||||
"s390x"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": "^20.19.0 || >=22.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/binding-linux-x64-gnu": {
|
"node_modules/@rolldown/binding-linux-x64-gnu": {
|
||||||
"version": "1.1.5",
|
"version": "1.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz",
|
||||||
@ -4346,103 +4176,6 @@
|
|||||||
"node": "^20.19.0 || >=22.12.0"
|
"node": "^20.19.0 || >=22.12.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rolldown/binding-openharmony-arm64": {
|
|
||||||
"version": "1.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz",
|
|
||||||
"integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"openharmony"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": "^20.19.0 || >=22.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/binding-wasm32-wasi": {
|
|
||||||
"version": "1.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz",
|
|
||||||
"integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==",
|
|
||||||
"cpu": [
|
|
||||||
"wasm32"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@emnapi/core": "1.11.1",
|
|
||||||
"@emnapi/runtime": "1.11.1",
|
|
||||||
"@napi-rs/wasm-runtime": "^1.1.6"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^20.19.0 || >=22.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/core": {
|
|
||||||
"version": "1.11.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz",
|
|
||||||
"integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@emnapi/wasi-threads": "1.2.2",
|
|
||||||
"tslib": "^2.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/runtime": {
|
|
||||||
"version": "1.11.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz",
|
|
||||||
"integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": "^2.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
|
||||||
"version": "1.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz",
|
|
||||||
"integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": "^2.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/binding-win32-arm64-msvc": {
|
|
||||||
"version": "1.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz",
|
|
||||||
"integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": "^20.19.0 || >=22.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/binding-win32-x64-msvc": {
|
|
||||||
"version": "1.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz",
|
|
||||||
"integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": "^20.19.0 || >=22.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rolldown/pluginutils": {
|
"node_modules/@rolldown/pluginutils": {
|
||||||
"version": "1.0.0-rc.3",
|
"version": "1.0.0-rc.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz",
|
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz",
|
||||||
@ -5041,118 +4774,6 @@
|
|||||||
"@tailwindcss/oxide-win32-x64-msvc": "4.3.3"
|
"@tailwindcss/oxide-win32-x64-msvc": "4.3.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/oxide-android-arm64": {
|
|
||||||
"version": "4.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz",
|
|
||||||
"integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"android"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 20"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-darwin-arm64": {
|
|
||||||
"version": "4.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz",
|
|
||||||
"integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 20"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-darwin-x64": {
|
|
||||||
"version": "4.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz",
|
|
||||||
"integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 20"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-freebsd-x64": {
|
|
||||||
"version": "4.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz",
|
|
||||||
"integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"freebsd"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 20"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
|
|
||||||
"version": "4.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz",
|
|
||||||
"integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==",
|
|
||||||
"cpu": [
|
|
||||||
"arm"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 20"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
|
|
||||||
"version": "4.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz",
|
|
||||||
"integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 20"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-linux-arm64-musl": {
|
|
||||||
"version": "4.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz",
|
|
||||||
"integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 20"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
|
"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
|
||||||
"version": "4.3.3",
|
"version": "4.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz",
|
||||||
@ -5185,51 +4806,6 @@
|
|||||||
"node": ">= 20"
|
"node": ">= 20"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/oxide-wasm32-wasi": {
|
|
||||||
"version": "4.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz",
|
|
||||||
"integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==",
|
|
||||||
"bundleDependencies": [
|
|
||||||
"@napi-rs/wasm-runtime",
|
|
||||||
"@emnapi/core",
|
|
||||||
"@emnapi/runtime",
|
|
||||||
"@tybys/wasm-util",
|
|
||||||
"@emnapi/wasi-threads",
|
|
||||||
"tslib"
|
|
||||||
],
|
|
||||||
"cpu": [
|
|
||||||
"wasm32"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@emnapi/core": "^1.11.1",
|
|
||||||
"@emnapi/runtime": "^1.11.1",
|
|
||||||
"@emnapi/wasi-threads": "^1.2.2",
|
|
||||||
"@napi-rs/wasm-runtime": "^1.1.4",
|
|
||||||
"@tybys/wasm-util": "^0.10.2",
|
|
||||||
"tslib": "^2.8.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
|
||||||
"version": "4.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz",
|
|
||||||
"integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 20"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
|
"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
|
||||||
"version": "4.3.3",
|
"version": "4.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz",
|
||||||
@ -5356,16 +4932,6 @@
|
|||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tybys/wasm-util": {
|
|
||||||
"version": "0.10.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz",
|
|
||||||
"integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": "^2.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/babel__core": {
|
"node_modules/@types/babel__core": {
|
||||||
"version": "7.20.5",
|
"version": "7.20.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
|
||||||
@ -5854,216 +5420,6 @@
|
|||||||
"url": "https://opencollective.com/eslint"
|
"url": "https://opencollective.com/eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@unrs/resolver-binding-android-arm-eabi": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==",
|
|
||||||
"cpu": [
|
|
||||||
"arm"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"android"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-android-arm64": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"android"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-darwin-arm64": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-darwin-x64": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-freebsd-x64": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"freebsd"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==",
|
|
||||||
"cpu": [
|
|
||||||
"arm"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-linux-arm-musleabihf": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==",
|
|
||||||
"cpu": [
|
|
||||||
"arm"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-linux-arm64-musl": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-linux-loong64-gnu": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==",
|
|
||||||
"cpu": [
|
|
||||||
"loong64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-linux-loong64-musl": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==",
|
|
||||||
"cpu": [
|
|
||||||
"loong64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==",
|
|
||||||
"cpu": [
|
|
||||||
"ppc64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==",
|
|
||||||
"cpu": [
|
|
||||||
"riscv64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==",
|
|
||||||
"cpu": [
|
|
||||||
"riscv64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==",
|
|
||||||
"cpu": [
|
|
||||||
"s390x"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-linux-x64-gnu": {
|
"node_modules/@unrs/resolver-binding-linux-x64-gnu": {
|
||||||
"version": "1.12.2",
|
"version": "1.12.2",
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz",
|
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz",
|
||||||
@ -6092,115 +5448,6 @@
|
|||||||
"linux"
|
"linux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@unrs/resolver-binding-openharmony-arm64": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"openharmony"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-wasm32-wasi": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==",
|
|
||||||
"cpu": [
|
|
||||||
"wasm32"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@emnapi/core": "1.10.0",
|
|
||||||
"@emnapi/runtime": "1.10.0",
|
|
||||||
"@napi-rs/wasm-runtime": "^1.1.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/core": {
|
|
||||||
"version": "1.10.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
|
|
||||||
"integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@emnapi/wasi-threads": "1.2.1",
|
|
||||||
"tslib": "^2.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/runtime": {
|
|
||||||
"version": "1.10.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
|
|
||||||
"integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": "^2.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
|
||||||
"version": "1.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
|
|
||||||
"integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": "^2.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==",
|
|
||||||
"cpu": [
|
|
||||||
"ia32"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@unrs/resolver-binding-win32-x64-msvc": {
|
|
||||||
"version": "1.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz",
|
|
||||||
"integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@vitejs/plugin-react": {
|
"node_modules/@vitejs/plugin-react": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz",
|
||||||
@ -6860,6 +6107,18 @@
|
|||||||
],
|
],
|
||||||
"license": "CC-BY-4.0"
|
"license": "CC-BY-4.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/canvas-dither": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/canvas-dither/-/canvas-dither-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-wT1RnV2y9SauibcsfMMCagQTnXmyQq2nJXuX5tTEvo0sXm1vVbJ2r8QxSC3fRQMY3ZgZVq1j54cOvmO4u+Lu/A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/canvas-flatten": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/canvas-flatten/-/canvas-flatten-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-UhHeKeWGS23Bm5teZiHk6NEOme1OKCpv6arFovV89dydt0Xz+U4HkPXAKBZS/hmpR15x5U9tDj1ieMQMTwvCAA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/chalk": {
|
"node_modules/chalk": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||||
@ -12313,6 +11572,18 @@
|
|||||||
"integrity": "sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==",
|
"integrity": "sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/resize-image-data": {
|
||||||
|
"version": "0.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/resize-image-data/-/resize-image-data-0.3.1.tgz",
|
||||||
|
"integrity": "sha512-6hVRn2S6W1cdycreA6Vth5XRN2NnGs7/RnVpxNw/1OCK8aCoevRFH2WprmQRZDnnH3e6awLv2tTIPuv7/7xeGg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@canvas/image-data": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/resolve": {
|
"node_modules/resolve": {
|
||||||
"version": "2.0.0-next.7",
|
"version": "2.0.0-next.7",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz",
|
||||||
|
|||||||
@ -38,6 +38,7 @@
|
|||||||
"@inertiajs/react": "^3.0.0",
|
"@inertiajs/react": "^3.0.0",
|
||||||
"@inertiajs/vite": "^3.0.0",
|
"@inertiajs/vite": "^3.0.0",
|
||||||
"@laravel/passkeys": "^0.2.0",
|
"@laravel/passkeys": "^0.2.0",
|
||||||
|
"@point-of-sale/receipt-printer-encoder": "^3.0.3",
|
||||||
"@radix-ui/react-avatar": "^1.1.3",
|
"@radix-ui/react-avatar": "^1.1.3",
|
||||||
"@radix-ui/react-checkbox": "^1.1.4",
|
"@radix-ui/react-checkbox": "^1.1.4",
|
||||||
"@radix-ui/react-collapsible": "^1.1.3",
|
"@radix-ui/react-collapsible": "^1.1.3",
|
||||||
|
|||||||
368
resources/js/hooks/use-thermal-printer.ts
Normal file
368
resources/js/hooks/use-thermal-printer.ts
Normal file
@ -0,0 +1,368 @@
|
|||||||
|
import ReceiptPrinterEncoder from '@point-of-sale/receipt-printer-encoder';
|
||||||
|
import { useCallback, useRef, useState } from 'react';
|
||||||
|
|
||||||
|
export type PrinterConnectionType = 'bluetooth' | 'usb';
|
||||||
|
export type PaperWidth = 58 | 80;
|
||||||
|
|
||||||
|
interface PrinterState {
|
||||||
|
connected: boolean;
|
||||||
|
connectionType: PrinterConnectionType | null;
|
||||||
|
printerName: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Receipt Builder (persis seperti contoh Vue) ── */
|
||||||
|
|
||||||
|
export function getPaperColumns(paperWidth: PaperWidth): number {
|
||||||
|
return paperWidth === 58 ? 32 : 48;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dashedLine(columns: number): string {
|
||||||
|
return '-'.repeat(columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
export type OrderReceiptItem = {
|
||||||
|
product_name: string;
|
||||||
|
variant_name: string;
|
||||||
|
quantity: string;
|
||||||
|
unit_price: string;
|
||||||
|
subtotal: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type OrderReceiptData = {
|
||||||
|
order_number: string;
|
||||||
|
created_at: string;
|
||||||
|
customer_name: string | null;
|
||||||
|
cashier_name: string;
|
||||||
|
items: OrderReceiptItem[];
|
||||||
|
subtotal: string;
|
||||||
|
discount: string;
|
||||||
|
nego_price: string | null;
|
||||||
|
total_amount: string;
|
||||||
|
notes: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EncodeOrderReceiptOptions = {
|
||||||
|
storeName: string;
|
||||||
|
storeAddress: string;
|
||||||
|
paperWidth: PaperWidth;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function encodeOrderReceipt(
|
||||||
|
order: OrderReceiptData,
|
||||||
|
options: EncodeOrderReceiptOptions,
|
||||||
|
): Uint8Array {
|
||||||
|
const columns = getPaperColumns(options.paperWidth);
|
||||||
|
const amountColumnWidth = 14;
|
||||||
|
const labelColumnWidth = columns - amountColumnWidth;
|
||||||
|
|
||||||
|
const encoder = new ReceiptPrinterEncoder({ columns });
|
||||||
|
|
||||||
|
encoder
|
||||||
|
.initialize()
|
||||||
|
.align('center')
|
||||||
|
.bold(true)
|
||||||
|
.text('')
|
||||||
|
.newline()
|
||||||
|
.text(options.storeName)
|
||||||
|
.newline()
|
||||||
|
.bold(false)
|
||||||
|
.newline();
|
||||||
|
|
||||||
|
for (const addressLine of options.storeAddress.split('\n')) {
|
||||||
|
const trimmed = addressLine.trim();
|
||||||
|
if (trimmed) {
|
||||||
|
encoder.align('center').text(trimmed).newline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
encoder.align('center').line(dashedLine(columns));
|
||||||
|
|
||||||
|
encoder
|
||||||
|
.align('left')
|
||||||
|
.line(`No : ${order.order_number}`)
|
||||||
|
.line(`Tgl : ${order.created_at}`);
|
||||||
|
|
||||||
|
if (order.customer_name) {
|
||||||
|
encoder.line(`Cust : ${order.customer_name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
encoder
|
||||||
|
.line(`Kasir: ${order.cashier_name}`)
|
||||||
|
.line(dashedLine(columns));
|
||||||
|
|
||||||
|
for (const item of order.items) {
|
||||||
|
encoder
|
||||||
|
.line(item.product_name)
|
||||||
|
.line(` ${item.variant_name}`)
|
||||||
|
.table(
|
||||||
|
[
|
||||||
|
{ width: labelColumnWidth, align: 'left' },
|
||||||
|
{ width: amountColumnWidth, align: 'right' },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
`${item.quantity} x ${item.unit_price}`,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(rowEncoder: any) =>
|
||||||
|
rowEncoder
|
||||||
|
.bold()
|
||||||
|
.text(item.subtotal)
|
||||||
|
.bold(false),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.newline();
|
||||||
|
}
|
||||||
|
|
||||||
|
encoder.line(dashedLine(columns));
|
||||||
|
|
||||||
|
const summaryRows = [
|
||||||
|
['Subtotal', order.subtotal],
|
||||||
|
['Diskon', order.discount],
|
||||||
|
];
|
||||||
|
|
||||||
|
if (order.nego_price) {
|
||||||
|
summaryRows.push(['Harga Nego', order.nego_price]);
|
||||||
|
}
|
||||||
|
|
||||||
|
summaryRows.push(['Total', order.total_amount]);
|
||||||
|
|
||||||
|
encoder.table(
|
||||||
|
[
|
||||||
|
{ width: labelColumnWidth, align: 'left' },
|
||||||
|
{ width: amountColumnWidth, align: 'right' },
|
||||||
|
],
|
||||||
|
summaryRows,
|
||||||
|
);
|
||||||
|
|
||||||
|
encoder
|
||||||
|
.newline()
|
||||||
|
.line(dashedLine(columns))
|
||||||
|
.align('center')
|
||||||
|
.line('Terima kasih atas kunjungannya')
|
||||||
|
.line('Silakan berbelanja kembali')
|
||||||
|
.newline(3)
|
||||||
|
.cut();
|
||||||
|
|
||||||
|
return encoder.encode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Printer Connection Hook ── */
|
||||||
|
|
||||||
|
export function useThermalPrinter() {
|
||||||
|
const [state, setState] = useState<PrinterState>({
|
||||||
|
connected: false,
|
||||||
|
connectionType: null,
|
||||||
|
printerName: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const bluetoothDeviceRef = useRef<BluetoothDevice | null>(null);
|
||||||
|
const bluetoothCharacteristicRef =
|
||||||
|
useRef<BluetoothCharacteristic | null>(null);
|
||||||
|
const usbDeviceRef = useRef<USBDevice | null>(null);
|
||||||
|
|
||||||
|
const disconnect = useCallback(async () => {
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
state.connectionType === 'bluetooth' &&
|
||||||
|
bluetoothDeviceRef.current
|
||||||
|
) {
|
||||||
|
bluetoothDeviceRef.current.gatt?.disconnect();
|
||||||
|
bluetoothDeviceRef.current = null;
|
||||||
|
bluetoothCharacteristicRef.current = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.connectionType === 'usb' && usbDeviceRef.current) {
|
||||||
|
usbDeviceRef.current.close();
|
||||||
|
usbDeviceRef.current = null;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// silent
|
||||||
|
}
|
||||||
|
|
||||||
|
setState({
|
||||||
|
connected: false,
|
||||||
|
connectionType: null,
|
||||||
|
printerName: null,
|
||||||
|
});
|
||||||
|
}, [state.connectionType]);
|
||||||
|
|
||||||
|
const connectBluetooth = useCallback(async () => {
|
||||||
|
if (!navigator.bluetooth) {
|
||||||
|
throw new Error(
|
||||||
|
'Web Bluetooth tidak didukung di browser ini. Gunakan Chrome atau Edge.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const device = await navigator.bluetooth.requestDevice({
|
||||||
|
acceptAllDevices: true,
|
||||||
|
optionalServices: [
|
||||||
|
'000018f0-0000-1000-8000-00805f9b34fb',
|
||||||
|
'00001800-0000-1000-8000-00805f9b34fb',
|
||||||
|
'00001801-0000-1000-8000-00805f9b34fb',
|
||||||
|
'00001101-0000-1000-8000-00805f9b34fb',
|
||||||
|
'0000ffe0-0000-1000-8000-00805f9b34fb',
|
||||||
|
'0000fee7-0000-1000-8000-00805f9b34fb',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const server = await device.gatt?.connect();
|
||||||
|
|
||||||
|
if (!server) {
|
||||||
|
throw new Error('Gagal terhubung ke perangkat Bluetooth.');
|
||||||
|
}
|
||||||
|
|
||||||
|
let characteristic: BluetoothCharacteristic | null = null;
|
||||||
|
|
||||||
|
const services = await server.getPrimaryServices();
|
||||||
|
for (const svc of services) {
|
||||||
|
try {
|
||||||
|
const chars = await svc.getCharacteristics();
|
||||||
|
const writable = chars.find(
|
||||||
|
(c) =>
|
||||||
|
c.properties.writeWithoutResponse ||
|
||||||
|
c.properties.write,
|
||||||
|
);
|
||||||
|
if (writable) {
|
||||||
|
characteristic = writable;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// skip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!characteristic) {
|
||||||
|
throw new Error(
|
||||||
|
'Tidak ditemukan characteristic yang bisa ditulis di printer ini.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bluetoothDeviceRef.current = device;
|
||||||
|
bluetoothCharacteristicRef.current = characteristic;
|
||||||
|
|
||||||
|
setState({
|
||||||
|
connected: true,
|
||||||
|
connectionType: 'bluetooth',
|
||||||
|
printerName: device.name ?? 'Printer Bluetooth',
|
||||||
|
});
|
||||||
|
|
||||||
|
return device.name ?? 'Printer Bluetooth';
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const connectUSB = useCallback(async () => {
|
||||||
|
if (!navigator.usb) {
|
||||||
|
throw new Error(
|
||||||
|
'Web USB tidak didukung di browser ini. Gunakan Chrome atau Edge.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const device = await navigator.usb.requestDevice({ filters: [] });
|
||||||
|
await device.open();
|
||||||
|
|
||||||
|
if (device.configuration === null) {
|
||||||
|
await device.selectConfiguration(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const iface =
|
||||||
|
device.configuration?.interfaces.find((i) =>
|
||||||
|
i.alternate.endpoints.some((e) => e.direction === 'out'),
|
||||||
|
) ?? device.configuration?.interfaces[0];
|
||||||
|
|
||||||
|
if (iface) {
|
||||||
|
await device.claimInterface(iface.interfaceNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
usbDeviceRef.current = device;
|
||||||
|
|
||||||
|
setState({
|
||||||
|
connected: true,
|
||||||
|
connectionType: 'usb',
|
||||||
|
printerName: device.productName ?? 'Printer USB',
|
||||||
|
});
|
||||||
|
|
||||||
|
return device.productName ?? 'Printer USB';
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const sendToBluetooth = useCallback(async (data: Uint8Array) => {
|
||||||
|
const characteristic = bluetoothCharacteristicRef.current;
|
||||||
|
if (!characteristic) {
|
||||||
|
throw new Error(
|
||||||
|
'Printer Bluetooth tidak terhubung.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const useWriteWithoutResponse =
|
||||||
|
characteristic.properties.writeWithoutResponse;
|
||||||
|
const chunkSize = 128;
|
||||||
|
|
||||||
|
for (let i = 0; i < data.length; i += chunkSize) {
|
||||||
|
const chunk = data.slice(i, i + chunkSize);
|
||||||
|
if (useWriteWithoutResponse) {
|
||||||
|
await characteristic.writeValueWithoutResponse(chunk);
|
||||||
|
} else {
|
||||||
|
await characteristic.writeValueWithResponse(chunk);
|
||||||
|
}
|
||||||
|
await new Promise((r) => setTimeout(r, 10));
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const sendToUSB = useCallback(async (data: Uint8Array) => {
|
||||||
|
const device = usbDeviceRef.current;
|
||||||
|
if (!device) {
|
||||||
|
throw new Error('Printer USB tidak terhubung.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const iface = device.configuration?.interfaces.find((i) =>
|
||||||
|
i.alternate.endpoints.some((e) => e.direction === 'out'),
|
||||||
|
);
|
||||||
|
const endpoint =
|
||||||
|
iface?.alternate.endpoints.find(
|
||||||
|
(e) => e.direction === 'out',
|
||||||
|
)?.endpointNumber ?? 1;
|
||||||
|
|
||||||
|
const chunkSize = 512;
|
||||||
|
for (let i = 0; i < data.length; i += chunkSize) {
|
||||||
|
const chunk = data.slice(i, i + chunkSize);
|
||||||
|
await device.transferOut(endpoint, chunk);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const print = useCallback(
|
||||||
|
async (data: Uint8Array) => {
|
||||||
|
if (!state.connected) {
|
||||||
|
throw new Error('Tidak ada printer yang terhubung.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.connectionType === 'bluetooth') {
|
||||||
|
await sendToBluetooth(data);
|
||||||
|
} else if (state.connectionType === 'usb') {
|
||||||
|
await sendToUSB(data);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[state.connected, state.connectionType, sendToBluetooth, sendToUSB],
|
||||||
|
);
|
||||||
|
|
||||||
|
const connect = useCallback(
|
||||||
|
async (type: PrinterConnectionType) => {
|
||||||
|
if (state.connected) {
|
||||||
|
await disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'bluetooth') {
|
||||||
|
return await connectBluetooth();
|
||||||
|
}
|
||||||
|
return await connectUSB();
|
||||||
|
},
|
||||||
|
[state.connected, disconnect, connectBluetooth, connectUSB],
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
connected: state.connected,
|
||||||
|
connectionType: state.connectionType,
|
||||||
|
printerName: state.printerName,
|
||||||
|
connect,
|
||||||
|
disconnect,
|
||||||
|
print,
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -1,7 +1,8 @@
|
|||||||
import { Head, Link, router } from '@inertiajs/react';
|
import { Head, Link, router, usePage } from '@inertiajs/react';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import { Plus } from 'lucide-react';
|
import { Bluetooth, Cable, Plus, Printer, Unplug } from 'lucide-react';
|
||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
|
import { toast } from 'sonner';
|
||||||
import { CardTable } from '@/components/card-table';
|
import { CardTable } from '@/components/card-table';
|
||||||
import { DatePicker } from '@/components/date-picker';
|
import { DatePicker } from '@/components/date-picker';
|
||||||
import { DeleteConfirmDialog } from '@/components/delete-confirm-dialog';
|
import { DeleteConfirmDialog } from '@/components/delete-confirm-dialog';
|
||||||
@ -17,6 +18,13 @@ import {
|
|||||||
ComboboxItem,
|
ComboboxItem,
|
||||||
ComboboxList,
|
ComboboxList,
|
||||||
} from '@/components/ui/combobox';
|
} from '@/components/ui/combobox';
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuSeparator,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from '@/components/ui/dropdown-menu';
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
@ -26,6 +34,7 @@ import {
|
|||||||
} from '@/components/ui/select';
|
} from '@/components/ui/select';
|
||||||
import { useCan } from '@/hooks/use-can';
|
import { useCan } from '@/hooks/use-can';
|
||||||
import { useServerTable } from '@/hooks/use-server-table';
|
import { useServerTable } from '@/hooks/use-server-table';
|
||||||
|
import { useThermalPrinter, encodeOrderReceipt } from '@/hooks/use-thermal-printer';
|
||||||
import {
|
import {
|
||||||
destroy,
|
destroy,
|
||||||
create as transactionCreate,
|
create as transactionCreate,
|
||||||
@ -89,8 +98,10 @@ export default function TransactionIndex({
|
|||||||
filterOptions,
|
filterOptions,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const { can } = useCan();
|
const { can } = useCan();
|
||||||
|
const { name: appName, address: appAddress } = usePage().props as unknown as { name: string; address: string };
|
||||||
const [deleting, setDeleting] = useState<Transaction | null>(null);
|
const [deleting, setDeleting] = useState<Transaction | null>(null);
|
||||||
const expand = useCardTableExpand(true);
|
const expand = useCardTableExpand(true);
|
||||||
|
const printer = useThermalPrinter();
|
||||||
|
|
||||||
const pagination = {
|
const pagination = {
|
||||||
current_page: transactions.current_page,
|
current_page: transactions.current_page,
|
||||||
@ -152,6 +163,52 @@ export default function TransactionIndex({
|
|||||||
router.patch(transactionUpdateStatus.url(transaction.id), { status });
|
router.patch(transactionUpdateStatus.url(transaction.id), { status });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handlePrintReceipt(transaction: Transaction, paperWidth: 58 | 80) {
|
||||||
|
if (!printer.connected) {
|
||||||
|
alert('Hubungkan printer terlebih dahulu.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rupiah = (n: number) => `Rp ${n.toLocaleString('id-ID')}`;
|
||||||
|
|
||||||
|
const items = (transaction.order_items ?? []).map((item) => ({
|
||||||
|
product_name: item.product_variant?.product?.name ?? '-',
|
||||||
|
variant_name: item.product_variant?.name ?? '-',
|
||||||
|
quantity: `${Number(item.quantity)}`,
|
||||||
|
unit_price: rupiah(Number(item.unit_price)),
|
||||||
|
subtotal: rupiah(Number(item.subtotal)),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const cashierName =
|
||||||
|
transaction.created_by?.user_profile?.full_name ?? '-';
|
||||||
|
|
||||||
|
const data = encodeOrderReceipt(
|
||||||
|
{
|
||||||
|
order_number: transaction.order_number,
|
||||||
|
created_at: format(new Date(transaction.created_at), 'dd/MM/yyyy HH:mm'),
|
||||||
|
customer_name: transaction.customer?.name ?? null,
|
||||||
|
cashier_name: cashierName,
|
||||||
|
items,
|
||||||
|
subtotal: rupiah(Number(transaction.subtotal)),
|
||||||
|
discount: rupiah(Number(transaction.discount)),
|
||||||
|
nego_price: transaction.nego_price != null && Number(transaction.nego_price) > 0
|
||||||
|
? rupiah(Number(transaction.nego_price))
|
||||||
|
: null,
|
||||||
|
total_amount: rupiah(Number(transaction.total_amount)),
|
||||||
|
notes: transaction.notes ?? null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
storeName: appName,
|
||||||
|
storeAddress: appAddress,
|
||||||
|
paperWidth,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
printer.print(data).catch((err: Error) => {
|
||||||
|
alert(`Gagal mencetak: ${err.message}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const filterToolbar = (
|
const filterToolbar = (
|
||||||
<FilterPopover
|
<FilterPopover
|
||||||
open={filterOpen}
|
open={filterOpen}
|
||||||
@ -358,14 +415,76 @@ export default function TransactionIndex({
|
|||||||
<PageHeader
|
<PageHeader
|
||||||
title="Transaksi"
|
title="Transaksi"
|
||||||
actions={
|
actions={
|
||||||
can('orders.create') ? (
|
<div className="flex items-center gap-2">
|
||||||
|
{printer.connected ? (
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button variant="outline" size="sm">
|
||||||
|
<Printer className="h-4 w-4" />
|
||||||
|
{printer.printerName}
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end">
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={async () => {
|
||||||
|
const name = await printer.disconnect();
|
||||||
|
toast.success('Printer diputuskan.');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Unplug className="h-4 w-4" />
|
||||||
|
Putuskan
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
) : (
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button variant="outline" size="sm">
|
||||||
|
<Printer className="h-4 w-4" />
|
||||||
|
Hubungkan Printer
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end">
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
const name = await printer.connect('bluetooth');
|
||||||
|
toast.success(`Terhubung ke ${name}`);
|
||||||
|
} catch (err) {
|
||||||
|
toast.error(err instanceof Error ? err.message : 'Gagal menghubungkan Bluetooth.');
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Bluetooth className="h-4 w-4" />
|
||||||
|
Hubungkan Bluetooth
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
const name = await printer.connect('usb');
|
||||||
|
toast.success(`Terhubung ke ${name}`);
|
||||||
|
} catch (err) {
|
||||||
|
toast.error(err instanceof Error ? err.message : 'Gagal menghubungkan USB.');
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Cable className="h-4 w-4" />
|
||||||
|
Hubungkan USB
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{can('orders.create') ? (
|
||||||
<Button asChild>
|
<Button asChild>
|
||||||
<Link href={transactionCreate.url()}>
|
<Link href={transactionCreate.url()}>
|
||||||
<Plus className="h-4 w-4" />
|
<Plus className="h-4 w-4" />
|
||||||
Tambah
|
Tambah
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
) : undefined
|
) : undefined}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -404,6 +523,7 @@ export default function TransactionIndex({
|
|||||||
}}
|
}}
|
||||||
onDelete={(t) => setDeleting(t)}
|
onDelete={(t) => setDeleting(t)}
|
||||||
onUpdateStatus={(t, status) => handleUpdateStatus(t, status)}
|
onUpdateStatus={(t, status) => handleUpdateStatus(t, status)}
|
||||||
|
onPrint={(t, pw) => handlePrintReceipt(t, pw)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
renderSubContent={(transaction) => (
|
renderSubContent={(transaction) => (
|
||||||
|
|||||||
@ -2,10 +2,17 @@ import { RowActions } from '@/components/row-actions';
|
|||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from '@/components/ui/dropdown-menu';
|
||||||
import { useCan } from '@/hooks/use-can';
|
import { useCan } from '@/hooks/use-can';
|
||||||
|
import type { PaperWidth } from '@/hooks/use-thermal-printer';
|
||||||
import { formatDateTime, formatNumber } from '@/lib/format';
|
import { formatDateTime, formatNumber } from '@/lib/format';
|
||||||
import { formatCurrency } from '@/lib/utils';
|
import { formatCurrency } from '@/lib/utils';
|
||||||
import { CheckCircle, ChevronDown, Pencil, Send, Trash2, XCircle } from 'lucide-react';
|
import { CheckCircle, ChevronDown, Pencil, Printer, Send, Trash2, XCircle } from 'lucide-react';
|
||||||
import type { Transaction } from './columns';
|
import type { Transaction } from './columns';
|
||||||
|
|
||||||
const STATUS_BADGE_CLASSES: Record<string, string> = {
|
const STATUS_BADGE_CLASSES: Record<string, string> = {
|
||||||
@ -24,6 +31,7 @@ export type TransactionCardRowParams = {
|
|||||||
onEdit: (transaction: Transaction) => void;
|
onEdit: (transaction: Transaction) => void;
|
||||||
onDelete: (transaction: Transaction) => void;
|
onDelete: (transaction: Transaction) => void;
|
||||||
onUpdateStatus: (transaction: Transaction, status: string) => void;
|
onUpdateStatus: (transaction: Transaction, status: string) => void;
|
||||||
|
onPrint: (transaction: Transaction, paperWidth: PaperWidth) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function TransactionCardRow({
|
export function TransactionCardRow({
|
||||||
@ -34,6 +42,7 @@ export function TransactionCardRow({
|
|||||||
onEdit,
|
onEdit,
|
||||||
onDelete,
|
onDelete,
|
||||||
onUpdateStatus,
|
onUpdateStatus,
|
||||||
|
onPrint,
|
||||||
}: TransactionCardRowParams) {
|
}: TransactionCardRowParams) {
|
||||||
const { can } = useCan();
|
const { can } = useCan();
|
||||||
const items = transaction.order_items ?? [];
|
const items = transaction.order_items ?? [];
|
||||||
@ -51,7 +60,6 @@ export function TransactionCardRow({
|
|||||||
);
|
);
|
||||||
const statusBadgeClass =
|
const statusBadgeClass =
|
||||||
STATUS_BADGE_CLASSES[transaction.status] ?? STATUS_BADGE_CLASSES.pending;
|
STATUS_BADGE_CLASSES[transaction.status] ?? STATUS_BADGE_CLASSES.pending;
|
||||||
console.log('transaction', transaction);
|
|
||||||
return (
|
return (
|
||||||
<Card className="overflow-hidden">
|
<Card className="overflow-hidden">
|
||||||
<CardContent className="p-0">
|
<CardContent className="p-0">
|
||||||
@ -188,7 +196,26 @@ console.log('transaction', transaction);
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{(can('orders.update') || can('orders.delete')) && (
|
<div className="flex shrink-0 items-center gap-1">
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button variant="ghost" size="icon" title="Cetak Struk">
|
||||||
|
<Printer className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end">
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={() => onPrint(transaction, 58)}
|
||||||
|
>
|
||||||
|
Struk 58mm
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={() => onPrint(transaction, 80)}
|
||||||
|
>
|
||||||
|
Struk 80mm
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
<RowActions
|
<RowActions
|
||||||
actions={[
|
actions={[
|
||||||
...(transaction.status === 'pending' && can('orders.update')
|
...(transaction.status === 'pending' && can('orders.update')
|
||||||
@ -240,7 +267,7 @@ console.log('transaction', transaction);
|
|||||||
]}
|
]}
|
||||||
wrapperClassName="flex shrink-0 items-center gap-1"
|
wrapperClassName="flex shrink-0 items-center gap-1"
|
||||||
/>
|
/>
|
||||||
)}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
35
resources/js/types/receipt-printer-encoder.d.ts
vendored
Normal file
35
resources/js/types/receipt-printer-encoder.d.ts
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
declare module '@point-of-sale/receipt-printer-encoder' {
|
||||||
|
interface ReceiptPrinterEncoderOptions {
|
||||||
|
language?: string;
|
||||||
|
codepageMapping?: Record<string, string>;
|
||||||
|
columns?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TableOptions {
|
||||||
|
width: number;
|
||||||
|
align: 'left' | 'center' | 'right';
|
||||||
|
}
|
||||||
|
|
||||||
|
type TableCell = string | ((encoder: ReceiptPrinterEncoder) => void);
|
||||||
|
|
||||||
|
class ReceiptPrinterEncoder {
|
||||||
|
constructor(options?: ReceiptPrinterEncoderOptions);
|
||||||
|
initialize(): this;
|
||||||
|
reset(): this;
|
||||||
|
align(align: 'left' | 'center' | 'right'): this;
|
||||||
|
bold(bold?: boolean): this;
|
||||||
|
underline(underline?: boolean): this;
|
||||||
|
invert(invert?: boolean): this;
|
||||||
|
width(width: number): this;
|
||||||
|
height(height: number): this;
|
||||||
|
text(text: string): this;
|
||||||
|
newline(count?: number): this;
|
||||||
|
line(text: string): this;
|
||||||
|
table(options: TableOptions[], rows: TableCell[][]): this;
|
||||||
|
cut(): this;
|
||||||
|
feed(lines?: number): this;
|
||||||
|
encode(): Uint8Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ReceiptPrinterEncoder;
|
||||||
|
}
|
||||||
174
resources/js/types/web-bluetooth-usb.d.ts
vendored
Normal file
174
resources/js/types/web-bluetooth-usb.d.ts
vendored
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
interface BluetoothDevice {
|
||||||
|
readonly id: string;
|
||||||
|
readonly name: string | null;
|
||||||
|
readonly gatt?: BluetoothRemoteGATTServer;
|
||||||
|
addEventListener(
|
||||||
|
type: 'gattserverdisconnected',
|
||||||
|
listener: EventListener,
|
||||||
|
): void;
|
||||||
|
removeEventListener(
|
||||||
|
type: 'gattserverdisconnected',
|
||||||
|
listener: EventListener,
|
||||||
|
): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BluetoothRemoteGATTServer {
|
||||||
|
readonly device: BluetoothDevice;
|
||||||
|
readonly connected: boolean;
|
||||||
|
connect(): Promise<BluetoothRemoteGATTServer>;
|
||||||
|
disconnect(): void;
|
||||||
|
getPrimaryService(
|
||||||
|
service: string,
|
||||||
|
): Promise<BluetoothRemoteGATTService>;
|
||||||
|
getPrimaryServices(): Promise<BluetoothRemoteGATTService[]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BluetoothRemoteGATTService {
|
||||||
|
readonly device: BluetoothDevice;
|
||||||
|
readonly uuid: string;
|
||||||
|
getCharacteristic(
|
||||||
|
characteristic: string,
|
||||||
|
): Promise<BluetoothCharacteristic>;
|
||||||
|
getCharacteristics(): Promise<BluetoothCharacteristic[]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BluetoothCharacteristic {
|
||||||
|
readonly uuid: string;
|
||||||
|
readonly service: BluetoothRemoteGATTService;
|
||||||
|
readonly properties: BluetoothCharacteristicProperties;
|
||||||
|
readValue(): Promise<DataView>;
|
||||||
|
writeValueWithResponse(value: BufferSource): Promise<void>;
|
||||||
|
writeValueWithoutResponse(value: BufferSource): Promise<void>;
|
||||||
|
startNotifications(): Promise<BluetoothCharacteristic>;
|
||||||
|
stopNotifications(): Promise<BluetoothCharacteristic>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BluetoothCharacteristicProperties {
|
||||||
|
readonly broadcast: boolean;
|
||||||
|
readonly read: boolean;
|
||||||
|
readonly writeWithoutResponse: boolean;
|
||||||
|
readonly write: boolean;
|
||||||
|
readonly notify: boolean;
|
||||||
|
readonly indicate: boolean;
|
||||||
|
readonly authenticatedSignedWrites: boolean;
|
||||||
|
readonly reliableWrite: boolean;
|
||||||
|
readonly writableAuxiliaries: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BluetoothRequestDeviceOptions {
|
||||||
|
filters?: BluetoothLEScanFilter[];
|
||||||
|
optionalServices?: string[];
|
||||||
|
acceptAllDevices?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BluetoothLEScanFilter {
|
||||||
|
services?: string[];
|
||||||
|
name?: string;
|
||||||
|
namePrefix?: string;
|
||||||
|
manufacturerData?: BluetoothManufacturerDataFilter[];
|
||||||
|
serviceData?: BluetoothServiceDataFilter[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BluetoothManufacturerDataFilter {
|
||||||
|
companyIdentifier: number;
|
||||||
|
dataPrefix?: BufferSource;
|
||||||
|
mask?: BufferSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BluetoothServiceDataFilter {
|
||||||
|
service: string;
|
||||||
|
dataPrefix?: BufferSource;
|
||||||
|
mask?: BufferSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Navigator {
|
||||||
|
bluetooth?: {
|
||||||
|
requestDevice(
|
||||||
|
options: BluetoothRequestDeviceOptions,
|
||||||
|
): Promise<BluetoothDevice>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface USBDevice {
|
||||||
|
readonly vendorId: number;
|
||||||
|
readonly productId: number;
|
||||||
|
readonly deviceVersionMajor: number;
|
||||||
|
readonly deviceVersionMinor: number;
|
||||||
|
readonly deviceVersionSubminor: number;
|
||||||
|
readonly manufacturerName: string | null;
|
||||||
|
readonly productName: string | null;
|
||||||
|
readonly serialNumber: string | null;
|
||||||
|
readonly configuration: USBConfiguration | null;
|
||||||
|
open(): Promise<void>;
|
||||||
|
close(): Promise<void>;
|
||||||
|
selectConfiguration(configurationValue: number): Promise<void>;
|
||||||
|
claimInterface(interfaceNumber: number): Promise<void>;
|
||||||
|
releaseInterface(interfaceNumber: number): Promise<void>;
|
||||||
|
transferOut(
|
||||||
|
endpointNumber: number,
|
||||||
|
data: BufferSource,
|
||||||
|
): Promise<USBOutTransferResult>;
|
||||||
|
transferIn(
|
||||||
|
endpointNumber: number,
|
||||||
|
length: number,
|
||||||
|
): Promise<USBInTransferResult>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface USBConfiguration {
|
||||||
|
readonly configurationValue: number;
|
||||||
|
readonly configurationName: string | null;
|
||||||
|
readonly interfaces: USBInterface[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface USBInterface {
|
||||||
|
readonly interfaceNumber: number;
|
||||||
|
readonly alternate: USBAlternateInterface;
|
||||||
|
readonly alternates: USBAlternateInterface[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface USBAlternateInterface {
|
||||||
|
readonly alternateSetting: number;
|
||||||
|
readonly interfaceClass: number;
|
||||||
|
readonly interfaceSubclass: number;
|
||||||
|
readonly interfaceProtocol: number;
|
||||||
|
readonly interfaceName: string | null;
|
||||||
|
readonly endpoints: USBEndpoint[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface USBEndpoint {
|
||||||
|
readonly endpointNumber: number;
|
||||||
|
readonly direction: 'in' | 'out';
|
||||||
|
readonly type: 'bulk' | 'interrupt' | 'isochronous' | 'control';
|
||||||
|
readonly packetSize: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface USBOutTransferResult {
|
||||||
|
readonly bytesWritten: number;
|
||||||
|
readonly status: 'ok' | 'stall' | 'babble';
|
||||||
|
}
|
||||||
|
|
||||||
|
interface USBInTransferResult {
|
||||||
|
readonly data: DataView | null;
|
||||||
|
readonly status: 'ok' | 'stall' | 'babble';
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Navigator {
|
||||||
|
usb?: {
|
||||||
|
requestDevice(
|
||||||
|
options: USBRequestDeviceOptions,
|
||||||
|
): Promise<USBDevice>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface USBRequestDeviceOptions {
|
||||||
|
filters: USBDeviceFilter[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface USBDeviceFilter {
|
||||||
|
vendorId?: number;
|
||||||
|
productId?: number;
|
||||||
|
classCode?: number;
|
||||||
|
subclassCode?: number;
|
||||||
|
protocolCode?: number;
|
||||||
|
serialNumber?: string;
|
||||||
|
}
|
||||||
@ -8,6 +8,9 @@ import { defineConfig } from 'vite';
|
|||||||
import { VitePWA } from 'vite-plugin-pwa';
|
import { VitePWA } from 'vite-plugin-pwa';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
optimizeDeps: {
|
||||||
|
include: ['@point-of-sale/receipt-printer-encoder'],
|
||||||
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
laravel({
|
laravel({
|
||||||
input: ['resources/css/app.css', 'resources/js/app.tsx'],
|
input: ['resources/css/app.css', 'resources/js/app.tsx'],
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user