@hadoku/task-ui-components 4.22.7 → 4.23.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../../node_modules/.pnpm/uqr@0.1.3/node_modules/uqr/dist/index.mjs"],"sourcesContent":["var QrCodeDataType = /* @__PURE__ */ ((QrCodeDataType2) => {\n QrCodeDataType2[QrCodeDataType2[\"Border\"] = -1] = \"Border\";\n QrCodeDataType2[QrCodeDataType2[\"Data\"] = 0] = \"Data\";\n QrCodeDataType2[QrCodeDataType2[\"Function\"] = 1] = \"Function\";\n QrCodeDataType2[QrCodeDataType2[\"Position\"] = 2] = \"Position\";\n QrCodeDataType2[QrCodeDataType2[\"Timing\"] = 3] = \"Timing\";\n QrCodeDataType2[QrCodeDataType2[\"Alignment\"] = 4] = \"Alignment\";\n return QrCodeDataType2;\n})(QrCodeDataType || {});\n\nconst LOW = [0, 1];\nconst MEDIUM = [1, 0];\nconst QUARTILE = [2, 3];\nconst HIGH = [3, 2];\nconst EccMap = {\n L: LOW,\n M: MEDIUM,\n Q: QUARTILE,\n H: HIGH\n};\nconst NUMERIC_REGEX = /^\\d*$/;\nconst ALPHANUMERIC_REGEX = /^[A-Z0-9 $%*+./:-]*$/;\nconst ALPHANUMERIC_CHARSET = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:\";\nconst MIN_VERSION = 1;\nconst MAX_VERSION = 40;\nconst PENALTY_N1 = 3;\nconst PENALTY_N2 = 3;\nconst PENALTY_N3 = 40;\nconst PENALTY_N4 = 10;\nconst ECC_CODEWORDS_PER_BLOCK = [\n // Version: (note that index 0 is for padding, and is set to an illegal value)\n // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level\n [-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],\n // Low\n [-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28],\n // Medium\n [-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],\n // Quartile\n [-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]\n // High\n];\nconst NUM_ERROR_CORRECTION_BLOCKS = [\n // Version: (note that index 0 is for padding, and is set to an illegal value)\n // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level\n [-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25],\n // Low\n [-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49],\n // Medium\n [-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68],\n // Quartile\n [-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81]\n // High\n];\nclass QrCode {\n /* -- Constructor (low level) and fields -- */\n // Creates a new QR Code with the given version number,\n // error correction level, data codeword bytes, and mask number.\n // This is a low-level API that most users should not use directly.\n // A mid-level API is the encodeSegments() function.\n constructor(version, ecc, dataCodewords, msk) {\n this.version = version;\n this.ecc = ecc;\n if (version < MIN_VERSION || version > MAX_VERSION)\n throw new RangeError(\"Version value out of range\");\n if (msk < -1 || msk > 7)\n throw new RangeError(\"Mask value out of range\");\n this.size = version * 4 + 17;\n const row = Array.from({ length: this.size }).fill(false);\n for (let i = 0; i < this.size; i++) {\n this.modules.push(row.slice());\n this.types.push(row.map(() => 0));\n }\n this.drawFunctionPatterns();\n const allCodewords = this.addEccAndInterleave(dataCodewords);\n this.drawCodewords(allCodewords);\n if (msk === -1) {\n let minPenalty = 1e9;\n for (let i = 0; i < 8; i++) {\n this.applyMask(i);\n this.drawFormatBits(i);\n const penalty = this.getPenaltyScore();\n if (penalty < minPenalty) {\n msk = i;\n minPenalty = penalty;\n }\n this.applyMask(i);\n }\n }\n this.mask = msk;\n this.applyMask(msk);\n this.drawFormatBits(msk);\n }\n /* -- Fields -- */\n // The width and height of this QR Code, measured in modules, between\n // 21 and 177 (inclusive). This is equal to version * 4 + 17.\n size;\n // The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive).\n // Even if a QR Code is created with automatic masking requested (mask = -1),\n // the resulting object still has a mask value between 0 and 7.\n mask;\n // The modules of this QR Code (false = light, true = dark).\n // Immutable after constructor finishes. Accessed through getModule().\n modules = [];\n types = [];\n /* -- Accessor methods -- */\n // Returns the color of the module (pixel) at the given coordinates, which is false\n // for light or true for dark. The top left corner has the coordinates (x=0, y=0).\n // If the given coordinates are out of bounds, then false (light) is returned.\n getModule(x, y) {\n return x >= 0 && x < this.size && y >= 0 && y < this.size && this.modules[y][x];\n }\n /* -- Private helper methods for constructor: Drawing function modules -- */\n // Reads this object's version field, and draws and marks all function modules.\n drawFunctionPatterns() {\n for (let i = 0; i < this.size; i++) {\n this.setFunctionModule(6, i, i % 2 === 0, QrCodeDataType.Timing);\n this.setFunctionModule(i, 6, i % 2 === 0, QrCodeDataType.Timing);\n }\n this.drawFinderPattern(3, 3);\n this.drawFinderPattern(this.size - 4, 3);\n this.drawFinderPattern(3, this.size - 4);\n const alignPatPos = this.getAlignmentPatternPositions();\n const numAlign = alignPatPos.length;\n for (let i = 0; i < numAlign; i++) {\n for (let j = 0; j < numAlign; j++) {\n if (!(i === 0 && j === 0 || i === 0 && j === numAlign - 1 || i === numAlign - 1 && j === 0))\n this.drawAlignmentPattern(alignPatPos[i], alignPatPos[j]);\n }\n }\n this.drawFormatBits(0);\n this.drawVersion();\n }\n // Draws two copies of the format bits (with its own error correction code)\n // based on the given mask and this object's error correction level field.\n drawFormatBits(mask) {\n const data = this.ecc[1] << 3 | mask;\n let rem = data;\n for (let i = 0; i < 10; i++)\n rem = rem << 1 ^ (rem >>> 9) * 1335;\n const bits = (data << 10 | rem) ^ 21522;\n for (let i = 0; i <= 5; i++)\n this.setFunctionModule(8, i, getBit(bits, i));\n this.setFunctionModule(8, 7, getBit(bits, 6));\n this.setFunctionModule(8, 8, getBit(bits, 7));\n this.setFunctionModule(7, 8, getBit(bits, 8));\n for (let i = 9; i < 15; i++)\n this.setFunctionModule(14 - i, 8, getBit(bits, i));\n for (let i = 0; i < 8; i++)\n this.setFunctionModule(this.size - 1 - i, 8, getBit(bits, i));\n for (let i = 8; i < 15; i++)\n this.setFunctionModule(8, this.size - 15 + i, getBit(bits, i));\n this.setFunctionModule(8, this.size - 8, true);\n }\n // Draws two copies of the version bits (with its own error correction code),\n // based on this object's version field, iff 7 <= version <= 40.\n drawVersion() {\n if (this.version < 7)\n return;\n let rem = this.version;\n for (let i = 0; i < 12; i++)\n rem = rem << 1 ^ (rem >>> 11) * 7973;\n const bits = this.version << 12 | rem;\n for (let i = 0; i < 18; i++) {\n const color = getBit(bits, i);\n const a = this.size - 11 + i % 3;\n const b = Math.floor(i / 3);\n this.setFunctionModule(a, b, color);\n this.setFunctionModule(b, a, color);\n }\n }\n // Draws a 9*9 finder pattern including the border separator,\n // with the center module at (x, y). Modules can be out of bounds.\n drawFinderPattern(x, y) {\n for (let dy = -4; dy <= 4; dy++) {\n for (let dx = -4; dx <= 4; dx++) {\n const dist = Math.max(Math.abs(dx), Math.abs(dy));\n const xx = x + dx;\n const yy = y + dy;\n if (xx >= 0 && xx < this.size && yy >= 0 && yy < this.size)\n this.setFunctionModule(xx, yy, dist !== 2 && dist !== 4, QrCodeDataType.Position);\n }\n }\n }\n // Draws a 5*5 alignment pattern, with the center module\n // at (x, y). All modules must be in bounds.\n drawAlignmentPattern(x, y) {\n for (let dy = -2; dy <= 2; dy++) {\n for (let dx = -2; dx <= 2; dx++) {\n this.setFunctionModule(\n x + dx,\n y + dy,\n Math.max(Math.abs(dx), Math.abs(dy)) !== 1,\n QrCodeDataType.Alignment\n );\n }\n }\n }\n // Sets the color of a module and marks it as a function module.\n // Only used by the constructor. Coordinates must be in bounds.\n setFunctionModule(x, y, isDark, type = QrCodeDataType.Function) {\n this.modules[y][x] = isDark;\n this.types[y][x] = type;\n }\n /* -- Private helper methods for constructor: Codewords and masking -- */\n // Returns a new byte string representing the given data with the appropriate error correction\n // codewords appended to it, based on this object's version and error correction level.\n addEccAndInterleave(data) {\n const ver = this.version;\n const ecl = this.ecc;\n if (data.length !== getNumDataCodewords(ver, ecl))\n throw new RangeError(\"Invalid argument\");\n const numBlocks = NUM_ERROR_CORRECTION_BLOCKS[ecl[0]][ver];\n const blockEccLen = ECC_CODEWORDS_PER_BLOCK[ecl[0]][ver];\n const rawCodewords = Math.floor(getNumRawDataModules(ver) / 8);\n const numShortBlocks = numBlocks - rawCodewords % numBlocks;\n const shortBlockLen = Math.floor(rawCodewords / numBlocks);\n const blocks = [];\n const rsDiv = reedSolomonComputeDivisor(blockEccLen);\n for (let i = 0, k = 0; i < numBlocks; i++) {\n const dat = data.slice(k, k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1));\n k += dat.length;\n const ecc = reedSolomonComputeRemainder(dat, rsDiv);\n if (i < numShortBlocks)\n dat.push(0);\n blocks.push(dat.concat(ecc));\n }\n const result = [];\n for (let i = 0; i < blocks[0].length; i++) {\n blocks.forEach((block, j) => {\n if (i !== shortBlockLen - blockEccLen || j >= numShortBlocks)\n result.push(block[i]);\n });\n }\n return result;\n }\n // Draws the given sequence of 8-bit codewords (data and error correction) onto the entire\n // data area of this QR Code. Function modules need to be marked off before this is called.\n drawCodewords(data) {\n if (data.length !== Math.floor(getNumRawDataModules(this.version) / 8))\n throw new RangeError(\"Invalid argument\");\n let i = 0;\n for (let right = this.size - 1; right >= 1; right -= 2) {\n if (right === 6)\n right = 5;\n for (let vert = 0; vert < this.size; vert++) {\n for (let j = 0; j < 2; j++) {\n const x = right - j;\n const upward = (right + 1 & 2) === 0;\n const y = upward ? this.size - 1 - vert : vert;\n if (!this.types[y][x] && i < data.length * 8) {\n this.modules[y][x] = getBit(data[i >>> 3], 7 - (i & 7));\n i++;\n }\n }\n }\n }\n }\n // XORs the codeword modules in this QR Code with the given mask pattern.\n // The function modules must be marked and the codeword bits must be drawn\n // before masking. Due to the arithmetic of XOR, calling applyMask() with\n // the same mask value a second time will undo the mask. A final well-formed\n // QR Code needs exactly one (not zero, two, etc.) mask applied.\n applyMask(mask) {\n if (mask < 0 || mask > 7)\n throw new RangeError(\"Mask value out of range\");\n for (let y = 0; y < this.size; y++) {\n for (let x = 0; x < this.size; x++) {\n let invert;\n switch (mask) {\n case 0:\n invert = (x + y) % 2 === 0;\n break;\n case 1:\n invert = y % 2 === 0;\n break;\n case 2:\n invert = x % 3 === 0;\n break;\n case 3:\n invert = (x + y) % 3 === 0;\n break;\n case 4:\n invert = (Math.floor(x / 3) + Math.floor(y / 2)) % 2 === 0;\n break;\n case 5:\n invert = x * y % 2 + x * y % 3 === 0;\n break;\n case 6:\n invert = (x * y % 2 + x * y % 3) % 2 === 0;\n break;\n case 7:\n invert = ((x + y) % 2 + x * y % 3) % 2 === 0;\n break;\n default:\n throw new Error(\"Unreachable\");\n }\n if (!this.types[y][x] && invert)\n this.modules[y][x] = !this.modules[y][x];\n }\n }\n }\n // Calculates and returns the penalty score based on state of this QR Code's current modules.\n // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.\n getPenaltyScore() {\n let result = 0;\n for (let y = 0; y < this.size; y++) {\n let runColor = false;\n let runX = 0;\n const runHistory = [0, 0, 0, 0, 0, 0, 0];\n for (let x = 0; x < this.size; x++) {\n if (this.modules[y][x] === runColor) {\n runX++;\n if (runX === 5)\n result += PENALTY_N1;\n else if (runX > 5)\n result++;\n } else {\n this.finderPenaltyAddHistory(runX, runHistory);\n if (!runColor)\n result += this.finderPenaltyCountPatterns(runHistory) * PENALTY_N3;\n runColor = this.modules[y][x];\n runX = 1;\n }\n }\n result += this.finderPenaltyTerminateAndCount(runColor, runX, runHistory) * PENALTY_N3;\n }\n for (let x = 0; x < this.size; x++) {\n let runColor = false;\n let runY = 0;\n const runHistory = [0, 0, 0, 0, 0, 0, 0];\n for (let y = 0; y < this.size; y++) {\n if (this.modules[y][x] === runColor) {\n runY++;\n if (runY === 5)\n result += PENALTY_N1;\n else if (runY > 5)\n result++;\n } else {\n this.finderPenaltyAddHistory(runY, runHistory);\n if (!runColor)\n result += this.finderPenaltyCountPatterns(runHistory) * PENALTY_N3;\n runColor = this.modules[y][x];\n runY = 1;\n }\n }\n result += this.finderPenaltyTerminateAndCount(runColor, runY, runHistory) * PENALTY_N3;\n }\n for (let y = 0; y < this.size - 1; y++) {\n for (let x = 0; x < this.size - 1; x++) {\n const color = this.modules[y][x];\n if (color === this.modules[y][x + 1] && color === this.modules[y + 1][x] && color === this.modules[y + 1][x + 1]) {\n result += PENALTY_N2;\n }\n }\n }\n let dark = 0;\n for (const row of this.modules)\n dark = row.reduce((sum, color) => sum + (color ? 1 : 0), dark);\n const total = this.size * this.size;\n const k = Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1;\n result += k * PENALTY_N4;\n return result;\n }\n /* -- Private helper functions -- */\n // Returns an ascending list of positions of alignment patterns for this version number.\n // Each position is in the range [0,177), and are used on both the x and y axes.\n // This could be implemented as lookup table of 40 variable-length lists of integers.\n getAlignmentPatternPositions() {\n if (this.version === 1) {\n return [];\n } else {\n const numAlign = Math.floor(this.version / 7) + 2;\n const step = this.version === 32 ? 26 : Math.ceil((this.version * 4 + 4) / (numAlign * 2 - 2)) * 2;\n const result = [6];\n for (let pos = this.size - 7; result.length < numAlign; pos -= step)\n result.splice(1, 0, pos);\n return result;\n }\n }\n // Can only be called immediately after a light run is added, and\n // returns either 0, 1, or 2. A helper function for getPenaltyScore().\n finderPenaltyCountPatterns(runHistory) {\n const n = runHistory[1];\n const core = n > 0 && runHistory[2] === n && runHistory[3] === n * 3 && runHistory[4] === n && runHistory[5] === n;\n return (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0) + (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0);\n }\n // Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore().\n finderPenaltyTerminateAndCount(currentRunColor, currentRunLength, runHistory) {\n if (currentRunColor) {\n this.finderPenaltyAddHistory(currentRunLength, runHistory);\n currentRunLength = 0;\n }\n currentRunLength += this.size;\n this.finderPenaltyAddHistory(currentRunLength, runHistory);\n return this.finderPenaltyCountPatterns(runHistory);\n }\n // Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore().\n finderPenaltyAddHistory(currentRunLength, runHistory) {\n if (runHistory[0] === 0)\n currentRunLength += this.size;\n runHistory.pop();\n runHistory.unshift(currentRunLength);\n }\n}\nfunction appendBits(val, len, bb) {\n if (len < 0 || len > 31 || val >>> len !== 0)\n throw new RangeError(\"Value out of range\");\n for (let i = len - 1; i >= 0; i--)\n bb.push(val >>> i & 1);\n}\nfunction getBit(x, i) {\n return (x >>> i & 1) !== 0;\n}\nclass QrSegment {\n // Creates a new QR Code segment with the given attributes and data.\n // The character count (numChars) must agree with the mode and the bit buffer length,\n // but the constraint isn't checked. The given bit buffer is cloned and stored.\n constructor(mode, numChars, bitData) {\n this.mode = mode;\n this.numChars = numChars;\n this.bitData = bitData;\n if (numChars < 0)\n throw new RangeError(\"Invalid argument\");\n this.bitData = bitData.slice();\n }\n /* -- Methods -- */\n // Returns a new copy of the data bits of this segment.\n getData() {\n return this.bitData.slice();\n }\n}\nconst MODE_NUMERIC = [1, 10, 12, 14];\nconst MODE_ALPHANUMERIC = [2, 9, 11, 13];\nconst MODE_BYTE = [4, 8, 16, 16];\nfunction numCharCountBits(mode, ver) {\n return mode[Math.floor((ver + 7) / 17) + 1];\n}\nfunction makeBytes(data) {\n const bb = [];\n for (const b of data)\n appendBits(b, 8, bb);\n return new QrSegment(MODE_BYTE, data.length, bb);\n}\nfunction makeNumeric(digits) {\n if (!isNumeric(digits))\n throw new RangeError(\"String contains non-numeric characters\");\n const bb = [];\n for (let i = 0; i < digits.length; ) {\n const n = Math.min(digits.length - i, 3);\n appendBits(Number.parseInt(digits.substring(i, i + n), 10), n * 3 + 1, bb);\n i += n;\n }\n return new QrSegment(MODE_NUMERIC, digits.length, bb);\n}\nfunction makeAlphanumeric(text) {\n if (!isAlphanumeric(text))\n throw new RangeError(\"String contains unencodable characters in alphanumeric mode\");\n const bb = [];\n let i;\n for (i = 0; i + 2 <= text.length; i += 2) {\n let temp = ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45;\n temp += ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1));\n appendBits(temp, 11, bb);\n }\n if (i < text.length)\n appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6, bb);\n return new QrSegment(MODE_ALPHANUMERIC, text.length, bb);\n}\nfunction makeSegments(text) {\n if (text === \"\")\n return [];\n else if (isNumeric(text))\n return [makeNumeric(text)];\n else if (isAlphanumeric(text))\n return [makeAlphanumeric(text)];\n else\n return [makeBytes(toUtf8ByteArray(text))];\n}\nfunction isNumeric(text) {\n return NUMERIC_REGEX.test(text);\n}\nfunction isAlphanumeric(text) {\n return ALPHANUMERIC_REGEX.test(text);\n}\nfunction getTotalBits(segs, version) {\n let result = 0;\n for (const seg of segs) {\n const ccbits = numCharCountBits(seg.mode, version);\n if (seg.numChars >= 1 << ccbits)\n return Number.POSITIVE_INFINITY;\n result += 4 + ccbits + seg.bitData.length;\n }\n return result;\n}\nfunction toUtf8ByteArray(str) {\n str = encodeURI(str);\n const result = [];\n for (let i = 0; i < str.length; i++) {\n if (str.charAt(i) !== \"%\") {\n result.push(str.charCodeAt(i));\n } else {\n result.push(Number.parseInt(str.substring(i + 1, i + 3), 16));\n i += 2;\n }\n }\n return result;\n}\nfunction getNumRawDataModules(ver) {\n if (ver < MIN_VERSION || ver > MAX_VERSION)\n throw new RangeError(\"Version number out of range\");\n let result = (16 * ver + 128) * ver + 64;\n if (ver >= 2) {\n const numAlign = Math.floor(ver / 7) + 2;\n result -= (25 * numAlign - 10) * numAlign - 55;\n if (ver >= 7)\n result -= 36;\n }\n return result;\n}\nfunction getNumDataCodewords(ver, ecl) {\n return Math.floor(getNumRawDataModules(ver) / 8) - ECC_CODEWORDS_PER_BLOCK[ecl[0]][ver] * NUM_ERROR_CORRECTION_BLOCKS[ecl[0]][ver];\n}\nfunction reedSolomonComputeDivisor(degree) {\n if (degree < 1 || degree > 255)\n throw new RangeError(\"Degree out of range\");\n const result = [];\n for (let i = 0; i < degree - 1; i++)\n result.push(0);\n result.push(1);\n let root = 1;\n for (let i = 0; i < degree; i++) {\n for (let j = 0; j < result.length; j++) {\n result[j] = reedSolomonMultiply(result[j], root);\n if (j + 1 < result.length)\n result[j] ^= result[j + 1];\n }\n root = reedSolomonMultiply(root, 2);\n }\n return result;\n}\nfunction reedSolomonComputeRemainder(data, divisor) {\n const result = divisor.map((_) => 0);\n for (const b of data) {\n const factor = b ^ result.shift();\n result.push(0);\n divisor.forEach((coef, i) => result[i] ^= reedSolomonMultiply(coef, factor));\n }\n return result;\n}\nfunction reedSolomonMultiply(x, y) {\n if (x >>> 8 !== 0 || y >>> 8 !== 0)\n throw new RangeError(\"Byte out of range\");\n let z = 0;\n for (let i = 7; i >= 0; i--) {\n z = z << 1 ^ (z >>> 7) * 285;\n z ^= (y >>> i & 1) * x;\n }\n return z;\n}\nfunction encodeSegments(segs, ecl, minVersion = 1, maxVersion = 40, mask = -1, boostEcl = true) {\n if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7) {\n throw new RangeError(\"Invalid value\");\n }\n let version;\n let dataUsedBits;\n for (version = minVersion; ; version++) {\n const dataCapacityBits2 = getNumDataCodewords(version, ecl) * 8;\n const usedBits = getTotalBits(segs, version);\n if (usedBits <= dataCapacityBits2) {\n dataUsedBits = usedBits;\n break;\n }\n if (version >= maxVersion)\n throw new RangeError(\"Data too long\");\n }\n for (const newEcl of [MEDIUM, QUARTILE, HIGH]) {\n if (boostEcl && dataUsedBits <= getNumDataCodewords(version, newEcl) * 8)\n ecl = newEcl;\n }\n const bb = [];\n for (const seg of segs) {\n appendBits(seg.mode[0], 4, bb);\n appendBits(seg.numChars, numCharCountBits(seg.mode, version), bb);\n for (const b of seg.getData())\n bb.push(b);\n }\n const dataCapacityBits = getNumDataCodewords(version, ecl) * 8;\n appendBits(0, Math.min(4, dataCapacityBits - bb.length), bb);\n appendBits(0, (8 - bb.length % 8) % 8, bb);\n for (let padByte = 236; bb.length < dataCapacityBits; padByte ^= 236 ^ 17)\n appendBits(padByte, 8, bb);\n const dataCodewords = Array.from({ length: Math.ceil(bb.length / 8) }, () => 0);\n bb.forEach((b, i) => dataCodewords[i >>> 3] |= b << 7 - (i & 7));\n return new QrCode(version, ecl, dataCodewords, mask);\n}\n\nfunction encode(data, options) {\n const {\n ecc = \"L\",\n boostEcc = false,\n minVersion = 1,\n maxVersion = 40,\n maskPattern = -1,\n border = 1\n } = options || {};\n const segment = typeof data === \"string\" ? makeSegments(data) : Array.isArray(data) ? [makeBytes(data)] : void 0;\n if (!segment)\n throw new Error(`uqr only supports encoding string and binary data, but got: ${typeof data}`);\n const qr = encodeSegments(\n segment,\n EccMap[ecc],\n minVersion,\n maxVersion,\n maskPattern,\n boostEcc\n );\n const result = addBorder({\n version: qr.version,\n maskPattern: qr.mask,\n size: qr.size,\n data: qr.modules,\n types: qr.types\n }, border);\n if (options?.invert)\n result.data = result.data.map((row) => row.map((mod) => !mod));\n options?.onEncoded?.(result);\n return result;\n}\nfunction addBorder(input, border = 1) {\n if (!border)\n return input;\n const { size } = input;\n const newSize = size + border * 2;\n input.size = newSize;\n input.data.forEach((row) => {\n for (let i = 0; i < border; i++) {\n row.unshift(false);\n row.push(false);\n }\n });\n for (let i = 0; i < border; i++) {\n input.data.unshift(Array.from({ length: newSize }, (_) => false));\n input.data.push(Array.from({ length: newSize }, (_) => false));\n }\n const b = QrCodeDataType.Border;\n input.types.forEach((row) => {\n for (let i = 0; i < border; i++) {\n row.unshift(b);\n row.push(b);\n }\n });\n for (let i = 0; i < border; i++) {\n input.types.unshift(Array.from({ length: newSize }, (_) => b));\n input.types.push(Array.from({ length: newSize }, (_) => b));\n }\n return input;\n}\nfunction getDataAt(data, x, y, defaults = false) {\n if (x < 0 || y < 0 || x >= data.length || y >= data.length)\n return defaults;\n return data[y][x];\n}\n\nfunction renderUnicode(data, options = {}) {\n const {\n whiteChar = \"\\u2588\",\n blackChar = \"\\u2591\"\n } = options;\n const result = encode(data, options);\n return result.data.map((row) => {\n return row.map((mod) => mod ? blackChar : whiteChar).join(\"\");\n }).join(\"\\n\");\n}\nfunction renderANSI(data, options = {}) {\n return renderUnicode(data, {\n ...options,\n blackChar: \"\\x1B[40m\\u3000\\x1B[0m\",\n whiteChar: \"\\x1B[47m\\u3000\\x1B[0m\"\n });\n}\nfunction renderUnicodeCompact(data, options = {}) {\n const palette = {\n WHITE_ALL: \"\\u2588\",\n WHITE_BLACK: \"\\u2580\",\n BLACK_WHITE: \"\\u2584\",\n BLACK_ALL: \" \"\n };\n const result = encode(data, options);\n const WHITE = false;\n const BLACK = true;\n const at = (x, y) => getDataAt(result.data, x, y, true);\n const lines = [];\n let line = \"\";\n for (let row = 0; row < result.size; row += 2) {\n for (let col = 0; col < result.size; col++) {\n if (at(col, row) === WHITE && at(col, row + 1) === WHITE)\n line += palette.WHITE_ALL;\n else if (at(col, row) === WHITE && at(col, row + 1) === BLACK)\n line += palette.WHITE_BLACK;\n else if (at(col, row) === BLACK && at(col, row + 1) === WHITE)\n line += palette.BLACK_WHITE;\n else\n line += palette.BLACK_ALL;\n }\n lines.push(line);\n line = \"\";\n }\n return lines.join(\"\\n\");\n}\n\nfunction escapeAttr(value) {\n return value.replace(/&/g, \"&amp;\").replace(/\"/g, \"&quot;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n}\nfunction renderSVG(data, options = {}) {\n const result = encode(data, options);\n const {\n pixelSize = 10,\n whiteColor = \"white\",\n blackColor = \"black\"\n } = options;\n const height = result.size * pixelSize;\n const width = result.size * pixelSize;\n let svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${width} ${height}\">`;\n const paths = [];\n for (let row = 0; row < result.size; row++) {\n for (let col = 0; col < result.size; col++) {\n const x = col * pixelSize;\n const y = row * pixelSize;\n if (result.data[row][col])\n paths.push(`M${x},${y}h${pixelSize}v${pixelSize}h-${pixelSize}z`);\n }\n }\n svg += `<rect fill=\"${escapeAttr(whiteColor)}\" width=\"${width}\" height=\"${height}\"/>`;\n svg += `<path fill=\"${escapeAttr(blackColor)}\" d=\"${paths.join(\"\")}\"/>`;\n svg += \"</svg>\";\n return svg;\n}\n\nexport { QrCodeDataType, encode, renderANSI, renderSVG, renderUnicode, renderUnicodeCompact };\n"],"names":[],"mappings":"AAAG,IAAC,iBAAkC,kBAAC,oBAAoB;AACzD,kBAAgB,gBAAgB,QAAQ,IAAI,EAAE,IAAI;AAClD,kBAAgB,gBAAgB,MAAM,IAAI,CAAC,IAAI;AAC/C,kBAAgB,gBAAgB,UAAU,IAAI,CAAC,IAAI;AACnD,kBAAgB,gBAAgB,UAAU,IAAI,CAAC,IAAI;AACnD,kBAAgB,gBAAgB,QAAQ,IAAI,CAAC,IAAI;AACjD,kBAAgB,gBAAgB,WAAW,IAAI,CAAC,IAAI;AACpD,SAAO;AACT,GAAG,kBAAkB,CAAA,CAAE;AAEvB,MAAM,MAAM,CAAC,GAAG,CAAC;AACjB,MAAM,SAAS,CAAC,GAAG,CAAC;AACpB,MAAM,WAAW,CAAC,GAAG,CAAC;AACtB,MAAM,OAAO,CAAC,GAAG,CAAC;AAClB,MAAM,SAAS;AAAA,EACb,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AACA,MAAM,gBAAgB;AACtB,MAAM,qBAAqB;AAC3B,MAAM,uBAAuB;AAC7B,MAAM,cAAc;AACpB,MAAM,cAAc;AACpB,MAAM,aAAa;AACnB,MAAM,aAAa;AACnB,MAAM,aAAa;AACnB,MAAM,aAAa;AACnB,MAAM,0BAA0B;AAAA;AAAA;AAAA,EAG9B,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAAA;AAAA,EAElK,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAAA;AAAA,EAEnK,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAAA;AAAA,EAEnK,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAAA;AAErK;AACA,MAAM,8BAA8B;AAAA;AAAA;AAAA,EAGlC,CAAC,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAAA;AAAA,EAE5I,CAAC,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAAA;AAAA,EAErJ,CAAC,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAAA;AAAA,EAExJ,CAAC,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAAA;AAE3J;AACA,MAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMX,YAAY,SAAS,KAAK,eAAe,KAAK;AAC5C,SAAK,UAAU;AACf,SAAK,MAAM;AACX,QAAI,UAAU,eAAe,UAAU;AACrC,YAAM,IAAI,WAAW,4BAA4B;AACnD,QAAI,MAAM,MAAM,MAAM;AACpB,YAAM,IAAI,WAAW,yBAAyB;AAChD,SAAK,OAAO,UAAU,IAAI;AAC1B,UAAM,MAAM,MAAM,KAAK,EAAE,QAAQ,KAAK,KAAI,CAAE,EAAE,KAAK,KAAK;AACxD,aAAS,IAAI,GAAG,IAAI,KAAK,MAAM,KAAK;AAClC,WAAK,QAAQ,KAAK,IAAI,MAAK,CAAE;AAC7B,WAAK,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,CAAC;AAAA,IAClC;AACA,SAAK,qBAAoB;AACzB,UAAM,eAAe,KAAK,oBAAoB,aAAa;AAC3D,SAAK,cAAc,YAAY;AAC/B,QAAI,QAAQ,IAAI;AACd,UAAI,aAAa;AACjB,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,aAAK,UAAU,CAAC;AAChB,aAAK,eAAe,CAAC;AACrB,cAAM,UAAU,KAAK,gBAAe;AACpC,YAAI,UAAU,YAAY;AACxB,gBAAM;AACN,uBAAa;AAAA,QACf;AACA,aAAK,UAAU,CAAC;AAAA,MAClB;AAAA,IACF;AACA,SAAK,OAAO;AACZ,SAAK,UAAU,GAAG;AAClB,SAAK,eAAe,GAAG;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAIA;AAAA;AAAA;AAAA;AAAA,EAIA;AAAA;AAAA;AAAA,EAGA,UAAU,CAAA;AAAA,EACV,QAAQ,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKR,UAAU,GAAG,GAAG;AACd,WAAO,KAAK,KAAK,IAAI,KAAK,QAAQ,KAAK,KAAK,IAAI,KAAK,QAAQ,KAAK,QAAQ,CAAC,EAAE,CAAC;AAAA,EAChF;AAAA;AAAA;AAAA,EAGA,uBAAuB;AACrB,aAAS,IAAI,GAAG,IAAI,KAAK,MAAM,KAAK;AAClC,WAAK,kBAAkB,GAAG,GAAG,IAAI,MAAM,GAAG,eAAe,MAAM;AAC/D,WAAK,kBAAkB,GAAG,GAAG,IAAI,MAAM,GAAG,eAAe,MAAM;AAAA,IACjE;AACA,SAAK,kBAAkB,GAAG,CAAC;AAC3B,SAAK,kBAAkB,KAAK,OAAO,GAAG,CAAC;AACvC,SAAK,kBAAkB,GAAG,KAAK,OAAO,CAAC;AACvC,UAAM,cAAc,KAAK,6BAA4B;AACrD,UAAM,WAAW,YAAY;AAC7B,aAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AACjC,eAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AACjC,YAAI,EAAE,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,WAAW,KAAK,MAAM,WAAW,KAAK,MAAM;AACvF,eAAK,qBAAqB,YAAY,CAAC,GAAG,YAAY,CAAC,CAAC;AAAA,MAC5D;AAAA,IACF;AACA,SAAK,eAAe,CAAC;AACrB,SAAK,YAAW;AAAA,EAClB;AAAA;AAAA;AAAA,EAGA,eAAe,MAAM;AACnB,UAAM,OAAO,KAAK,IAAI,CAAC,KAAK,IAAI;AAChC,QAAI,MAAM;AACV,aAAS,IAAI,GAAG,IAAI,IAAI;AACtB,YAAM,OAAO,KAAK,QAAQ,KAAK;AACjC,UAAM,QAAQ,QAAQ,KAAK,OAAO;AAClC,aAAS,IAAI,GAAG,KAAK,GAAG;AACtB,WAAK,kBAAkB,GAAG,GAAG,OAAO,MAAM,CAAC,CAAC;AAC9C,SAAK,kBAAkB,GAAG,GAAG,OAAO,MAAM,CAAC,CAAC;AAC5C,SAAK,kBAAkB,GAAG,GAAG,OAAO,MAAM,CAAC,CAAC;AAC5C,SAAK,kBAAkB,GAAG,GAAG,OAAO,MAAM,CAAC,CAAC;AAC5C,aAAS,IAAI,GAAG,IAAI,IAAI;AACtB,WAAK,kBAAkB,KAAK,GAAG,GAAG,OAAO,MAAM,CAAC,CAAC;AACnD,aAAS,IAAI,GAAG,IAAI,GAAG;AACrB,WAAK,kBAAkB,KAAK,OAAO,IAAI,GAAG,GAAG,OAAO,MAAM,CAAC,CAAC;AAC9D,aAAS,IAAI,GAAG,IAAI,IAAI;AACtB,WAAK,kBAAkB,GAAG,KAAK,OAAO,KAAK,GAAG,OAAO,MAAM,CAAC,CAAC;AAC/D,SAAK,kBAAkB,GAAG,KAAK,OAAO,GAAG,IAAI;AAAA,EAC/C;AAAA;AAAA;AAAA,EAGA,cAAc;AACZ,QAAI,KAAK,UAAU;AACjB;AACF,QAAI,MAAM,KAAK;AACf,aAAS,IAAI,GAAG,IAAI,IAAI;AACtB,YAAM,OAAO,KAAK,QAAQ,MAAM;AAClC,UAAM,OAAO,KAAK,WAAW,KAAK;AAClC,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,YAAM,QAAQ,OAAO,MAAM,CAAC;AAC5B,YAAM,IAAI,KAAK,OAAO,KAAK,IAAI;AAC/B,YAAM,IAAI,KAAK,MAAM,IAAI,CAAC;AAC1B,WAAK,kBAAkB,GAAG,GAAG,KAAK;AAClC,WAAK,kBAAkB,GAAG,GAAG,KAAK;AAAA,IACpC;AAAA,EACF;AAAA;AAAA;AAAA,EAGA,kBAAkB,GAAG,GAAG;AACtB,aAAS,KAAK,IAAI,MAAM,GAAG,MAAM;AAC/B,eAAS,KAAK,IAAI,MAAM,GAAG,MAAM;AAC/B,cAAM,OAAO,KAAK,IAAI,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC;AAChD,cAAM,KAAK,IAAI;AACf,cAAM,KAAK,IAAI;AACf,YAAI,MAAM,KAAK,KAAK,KAAK,QAAQ,MAAM,KAAK,KAAK,KAAK;AACpD,eAAK,kBAAkB,IAAI,IAAI,SAAS,KAAK,SAAS,GAAG,eAAe,QAAQ;AAAA,MACpF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA,EAGA,qBAAqB,GAAG,GAAG;AACzB,aAAS,KAAK,IAAI,MAAM,GAAG,MAAM;AAC/B,eAAS,KAAK,IAAI,MAAM,GAAG,MAAM;AAC/B,aAAK;AAAA,UACH,IAAI;AAAA,UACJ,IAAI;AAAA,UACJ,KAAK,IAAI,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,MAAM;AAAA,UACzC,eAAe;AAAA,QACzB;AAAA,MACM;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA,EAGA,kBAAkB,GAAG,GAAG,QAAQ,OAAO,eAAe,UAAU;AAC9D,SAAK,QAAQ,CAAC,EAAE,CAAC,IAAI;AACrB,SAAK,MAAM,CAAC,EAAE,CAAC,IAAI;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAIA,oBAAoB,MAAM;AACxB,UAAM,MAAM,KAAK;AACjB,UAAM,MAAM,KAAK;AACjB,QAAI,KAAK,WAAW,oBAAoB,KAAK,GAAG;AAC9C,YAAM,IAAI,WAAW,kBAAkB;AACzC,UAAM,YAAY,4BAA4B,IAAI,CAAC,CAAC,EAAE,GAAG;AACzD,UAAM,cAAc,wBAAwB,IAAI,CAAC,CAAC,EAAE,GAAG;AACvD,UAAM,eAAe,KAAK,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAC7D,UAAM,iBAAiB,YAAY,eAAe;AAClD,UAAM,gBAAgB,KAAK,MAAM,eAAe,SAAS;AACzD,UAAM,SAAS,CAAA;AACf,UAAM,QAAQ,0BAA0B,WAAW;AACnD,aAAS,IAAI,GAAG,IAAI,GAAG,IAAI,WAAW,KAAK;AACzC,YAAM,MAAM,KAAK,MAAM,GAAG,IAAI,gBAAgB,eAAe,IAAI,iBAAiB,IAAI,EAAE;AACxF,WAAK,IAAI;AACT,YAAM,MAAM,4BAA4B,KAAK,KAAK;AAClD,UAAI,IAAI;AACN,YAAI,KAAK,CAAC;AACZ,aAAO,KAAK,IAAI,OAAO,GAAG,CAAC;AAAA,IAC7B;AACA,UAAM,SAAS,CAAA;AACf,aAAS,IAAI,GAAG,IAAI,OAAO,CAAC,EAAE,QAAQ,KAAK;AACzC,aAAO,QAAQ,CAAC,OAAO,MAAM;AAC3B,YAAI,MAAM,gBAAgB,eAAe,KAAK;AAC5C,iBAAO,KAAK,MAAM,CAAC,CAAC;AAAA,MACxB,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA,EAGA,cAAc,MAAM;AAClB,QAAI,KAAK,WAAW,KAAK,MAAM,qBAAqB,KAAK,OAAO,IAAI,CAAC;AACnE,YAAM,IAAI,WAAW,kBAAkB;AACzC,QAAI,IAAI;AACR,aAAS,QAAQ,KAAK,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG;AACtD,UAAI,UAAU;AACZ,gBAAQ;AACV,eAAS,OAAO,GAAG,OAAO,KAAK,MAAM,QAAQ;AAC3C,iBAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,gBAAM,IAAI,QAAQ;AAClB,gBAAM,UAAU,QAAQ,IAAI,OAAO;AACnC,gBAAM,IAAI,SAAS,KAAK,OAAO,IAAI,OAAO;AAC1C,cAAI,CAAC,KAAK,MAAM,CAAC,EAAE,CAAC,KAAK,IAAI,KAAK,SAAS,GAAG;AAC5C,iBAAK,QAAQ,CAAC,EAAE,CAAC,IAAI,OAAO,KAAK,MAAM,CAAC,GAAG,KAAK,IAAI,EAAE;AACtD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,MAAM;AACd,QAAI,OAAO,KAAK,OAAO;AACrB,YAAM,IAAI,WAAW,yBAAyB;AAChD,aAAS,IAAI,GAAG,IAAI,KAAK,MAAM,KAAK;AAClC,eAAS,IAAI,GAAG,IAAI,KAAK,MAAM,KAAK;AAClC,YAAI;AACJ,gBAAQ,MAAI;AAAA,UACV,KAAK;AACH,sBAAU,IAAI,KAAK,MAAM;AACzB;AAAA,UACF,KAAK;AACH,qBAAS,IAAI,MAAM;AACnB;AAAA,UACF,KAAK;AACH,qBAAS,IAAI,MAAM;AACnB;AAAA,UACF,KAAK;AACH,sBAAU,IAAI,KAAK,MAAM;AACzB;AAAA,UACF,KAAK;AACH,sBAAU,KAAK,MAAM,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,KAAK,MAAM;AACzD;AAAA,UACF,KAAK;AACH,qBAAS,IAAI,IAAI,IAAI,IAAI,IAAI,MAAM;AACnC;AAAA,UACF,KAAK;AACH,sBAAU,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,MAAM;AACzC;AAAA,UACF,KAAK;AACH,uBAAW,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,MAAM;AAC3C;AAAA,UACF;AACE,kBAAM,IAAI,MAAM,aAAa;AAAA,QACzC;AACQ,YAAI,CAAC,KAAK,MAAM,CAAC,EAAE,CAAC,KAAK;AACvB,eAAK,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA,EAGA,kBAAkB;AAChB,QAAI,SAAS;AACb,aAAS,IAAI,GAAG,IAAI,KAAK,MAAM,KAAK;AAClC,UAAI,WAAW;AACf,UAAI,OAAO;AACX,YAAM,aAAa,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AACvC,eAAS,IAAI,GAAG,IAAI,KAAK,MAAM,KAAK;AAClC,YAAI,KAAK,QAAQ,CAAC,EAAE,CAAC,MAAM,UAAU;AACnC;AACA,cAAI,SAAS;AACX,sBAAU;AAAA,mBACH,OAAO;AACd;AAAA,QACJ,OAAO;AACL,eAAK,wBAAwB,MAAM,UAAU;AAC7C,cAAI,CAAC;AACH,sBAAU,KAAK,2BAA2B,UAAU,IAAI;AAC1D,qBAAW,KAAK,QAAQ,CAAC,EAAE,CAAC;AAC5B,iBAAO;AAAA,QACT;AAAA,MACF;AACA,gBAAU,KAAK,+BAA+B,UAAU,MAAM,UAAU,IAAI;AAAA,IAC9E;AACA,aAAS,IAAI,GAAG,IAAI,KAAK,MAAM,KAAK;AAClC,UAAI,WAAW;AACf,UAAI,OAAO;AACX,YAAM,aAAa,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AACvC,eAAS,IAAI,GAAG,IAAI,KAAK,MAAM,KAAK;AAClC,YAAI,KAAK,QAAQ,CAAC,EAAE,CAAC,MAAM,UAAU;AACnC;AACA,cAAI,SAAS;AACX,sBAAU;AAAA,mBACH,OAAO;AACd;AAAA,QACJ,OAAO;AACL,eAAK,wBAAwB,MAAM,UAAU;AAC7C,cAAI,CAAC;AACH,sBAAU,KAAK,2BAA2B,UAAU,IAAI;AAC1D,qBAAW,KAAK,QAAQ,CAAC,EAAE,CAAC;AAC5B,iBAAO;AAAA,QACT;AAAA,MACF;AACA,gBAAU,KAAK,+BAA+B,UAAU,MAAM,UAAU,IAAI;AAAA,IAC9E;AACA,aAAS,IAAI,GAAG,IAAI,KAAK,OAAO,GAAG,KAAK;AACtC,eAAS,IAAI,GAAG,IAAI,KAAK,OAAO,GAAG,KAAK;AACtC,cAAM,QAAQ,KAAK,QAAQ,CAAC,EAAE,CAAC;AAC/B,YAAI,UAAU,KAAK,QAAQ,CAAC,EAAE,IAAI,CAAC,KAAK,UAAU,KAAK,QAAQ,IAAI,CAAC,EAAE,CAAC,KAAK,UAAU,KAAK,QAAQ,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG;AAChH,oBAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AACA,QAAI,OAAO;AACX,eAAW,OAAO,KAAK;AACrB,aAAO,IAAI,OAAO,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,IAAI,IAAI;AAC/D,UAAM,QAAQ,KAAK,OAAO,KAAK;AAC/B,UAAM,IAAI,KAAK,KAAK,KAAK,IAAI,OAAO,KAAK,QAAQ,EAAE,IAAI,KAAK,IAAI;AAChE,cAAU,IAAI;AACd,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,+BAA+B;AAC7B,QAAI,KAAK,YAAY,GAAG;AACtB,aAAO,CAAA;AAAA,IACT,OAAO;AACL,YAAM,WAAW,KAAK,MAAM,KAAK,UAAU,CAAC,IAAI;AAChD,YAAM,OAAO,KAAK,YAAY,KAAK,KAAK,KAAK,MAAM,KAAK,UAAU,IAAI,MAAM,WAAW,IAAI,EAAE,IAAI;AACjG,YAAM,SAAS,CAAC,CAAC;AACjB,eAAS,MAAM,KAAK,OAAO,GAAG,OAAO,SAAS,UAAU,OAAO;AAC7D,eAAO,OAAO,GAAG,GAAG,GAAG;AACzB,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA,EAGA,2BAA2B,YAAY;AACrC,UAAM,IAAI,WAAW,CAAC;AACtB,UAAM,OAAO,IAAI,KAAK,WAAW,CAAC,MAAM,KAAK,WAAW,CAAC,MAAM,IAAI,KAAK,WAAW,CAAC,MAAM,KAAK,WAAW,CAAC,MAAM;AACjH,YAAQ,QAAQ,WAAW,CAAC,KAAK,IAAI,KAAK,WAAW,CAAC,KAAK,IAAI,IAAI,MAAM,QAAQ,WAAW,CAAC,KAAK,IAAI,KAAK,WAAW,CAAC,KAAK,IAAI,IAAI;AAAA,EACtI;AAAA;AAAA,EAEA,+BAA+B,iBAAiB,kBAAkB,YAAY;AAC5E,QAAI,iBAAiB;AACnB,WAAK,wBAAwB,kBAAkB,UAAU;AACzD,yBAAmB;AAAA,IACrB;AACA,wBAAoB,KAAK;AACzB,SAAK,wBAAwB,kBAAkB,UAAU;AACzD,WAAO,KAAK,2BAA2B,UAAU;AAAA,EACnD;AAAA;AAAA,EAEA,wBAAwB,kBAAkB,YAAY;AACpD,QAAI,WAAW,CAAC,MAAM;AACpB,0BAAoB,KAAK;AAC3B,eAAW,IAAG;AACd,eAAW,QAAQ,gBAAgB;AAAA,EACrC;AACF;AACA,SAAS,WAAW,KAAK,KAAK,IAAI;AAChC,MAAI,MAAM,KAAK,MAAM,MAAM,QAAQ,QAAQ;AACzC,UAAM,IAAI,WAAW,oBAAoB;AAC3C,WAAS,IAAI,MAAM,GAAG,KAAK,GAAG;AAC5B,OAAG,KAAK,QAAQ,IAAI,CAAC;AACzB;AACA,SAAS,OAAO,GAAG,GAAG;AACpB,UAAQ,MAAM,IAAI,OAAO;AAC3B;AACA,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA,EAId,YAAY,MAAM,UAAU,SAAS;AACnC,SAAK,OAAO;AACZ,SAAK,WAAW;AAChB,SAAK,UAAU;AACf,QAAI,WAAW;AACb,YAAM,IAAI,WAAW,kBAAkB;AACzC,SAAK,UAAU,QAAQ,MAAK;AAAA,EAC9B;AAAA;AAAA;AAAA,EAGA,UAAU;AACR,WAAO,KAAK,QAAQ,MAAK;AAAA,EAC3B;AACF;AACA,MAAM,eAAe,CAAC,GAAG,IAAI,IAAI,EAAE;AACnC,MAAM,oBAAoB,CAAC,GAAG,GAAG,IAAI,EAAE;AACvC,MAAM,YAAY,CAAC,GAAG,GAAG,IAAI,EAAE;AAC/B,SAAS,iBAAiB,MAAM,KAAK;AACnC,SAAO,KAAK,KAAK,OAAO,MAAM,KAAK,EAAE,IAAI,CAAC;AAC5C;AACA,SAAS,UAAU,MAAM;AACvB,QAAM,KAAK,CAAA;AACX,aAAW,KAAK;AACd,eAAW,GAAG,GAAG,EAAE;AACrB,SAAO,IAAI,UAAU,WAAW,KAAK,QAAQ,EAAE;AACjD;AACA,SAAS,YAAY,QAAQ;AAC3B,MAAI,CAAC,UAAU,MAAM;AACnB,UAAM,IAAI,WAAW,wCAAwC;AAC/D,QAAM,KAAK,CAAA;AACX,WAAS,IAAI,GAAG,IAAI,OAAO,UAAU;AACnC,UAAM,IAAI,KAAK,IAAI,OAAO,SAAS,GAAG,CAAC;AACvC,eAAW,OAAO,SAAS,OAAO,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,GAAG,EAAE;AACzE,SAAK;AAAA,EACP;AACA,SAAO,IAAI,UAAU,cAAc,OAAO,QAAQ,EAAE;AACtD;AACA,SAAS,iBAAiB,MAAM;AAC9B,MAAI,CAAC,eAAe,IAAI;AACtB,UAAM,IAAI,WAAW,6DAA6D;AACpF,QAAM,KAAK,CAAA;AACX,MAAI;AACJ,OAAK,IAAI,GAAG,IAAI,KAAK,KAAK,QAAQ,KAAK,GAAG;AACxC,QAAI,OAAO,qBAAqB,QAAQ,KAAK,OAAO,CAAC,CAAC,IAAI;AAC1D,YAAQ,qBAAqB,QAAQ,KAAK,OAAO,IAAI,CAAC,CAAC;AACvD,eAAW,MAAM,IAAI,EAAE;AAAA,EACzB;AACA,MAAI,IAAI,KAAK;AACX,eAAW,qBAAqB,QAAQ,KAAK,OAAO,CAAC,CAAC,GAAG,GAAG,EAAE;AAChE,SAAO,IAAI,UAAU,mBAAmB,KAAK,QAAQ,EAAE;AACzD;AACA,SAAS,aAAa,MAAM;AAC1B,MAAI,SAAS;AACX,WAAO,CAAA;AAAA,WACA,UAAU,IAAI;AACrB,WAAO,CAAC,YAAY,IAAI,CAAC;AAAA,WAClB,eAAe,IAAI;AAC1B,WAAO,CAAC,iBAAiB,IAAI,CAAC;AAAA;AAE9B,WAAO,CAAC,UAAU,gBAAgB,IAAI,CAAC,CAAC;AAC5C;AACA,SAAS,UAAU,MAAM;AACvB,SAAO,cAAc,KAAK,IAAI;AAChC;AACA,SAAS,eAAe,MAAM;AAC5B,SAAO,mBAAmB,KAAK,IAAI;AACrC;AACA,SAAS,aAAa,MAAM,SAAS;AACnC,MAAI,SAAS;AACb,aAAW,OAAO,MAAM;AACtB,UAAM,SAAS,iBAAiB,IAAI,MAAM,OAAO;AACjD,QAAI,IAAI,YAAY,KAAK;AACvB,aAAO,OAAO;AAChB,cAAU,IAAI,SAAS,IAAI,QAAQ;AAAA,EACrC;AACA,SAAO;AACT;AACA,SAAS,gBAAgB,KAAK;AAC5B,QAAM,UAAU,GAAG;AACnB,QAAM,SAAS,CAAA;AACf,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,QAAI,IAAI,OAAO,CAAC,MAAM,KAAK;AACzB,aAAO,KAAK,IAAI,WAAW,CAAC,CAAC;AAAA,IAC/B,OAAO;AACL,aAAO,KAAK,OAAO,SAAS,IAAI,UAAU,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AAC5D,WAAK;AAAA,IACP;AAAA,EACF;AACA,SAAO;AACT;AACA,SAAS,qBAAqB,KAAK;AACjC,MAAI,MAAM,eAAe,MAAM;AAC7B,UAAM,IAAI,WAAW,6BAA6B;AACpD,MAAI,UAAU,KAAK,MAAM,OAAO,MAAM;AACtC,MAAI,OAAO,GAAG;AACZ,UAAM,WAAW,KAAK,MAAM,MAAM,CAAC,IAAI;AACvC,eAAW,KAAK,WAAW,MAAM,WAAW;AAC5C,QAAI,OAAO;AACT,gBAAU;AAAA,EACd;AACA,SAAO;AACT;AACA,SAAS,oBAAoB,KAAK,KAAK;AACrC,SAAO,KAAK,MAAM,qBAAqB,GAAG,IAAI,CAAC,IAAI,wBAAwB,IAAI,CAAC,CAAC,EAAE,GAAG,IAAI,4BAA4B,IAAI,CAAC,CAAC,EAAE,GAAG;AACnI;AACA,SAAS,0BAA0B,QAAQ;AACzC,MAAI,SAAS,KAAK,SAAS;AACzB,UAAM,IAAI,WAAW,qBAAqB;AAC5C,QAAM,SAAS,CAAA;AACf,WAAS,IAAI,GAAG,IAAI,SAAS,GAAG;AAC9B,WAAO,KAAK,CAAC;AACf,SAAO,KAAK,CAAC;AACb,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,aAAO,CAAC,IAAI,oBAAoB,OAAO,CAAC,GAAG,IAAI;AAC/C,UAAI,IAAI,IAAI,OAAO;AACjB,eAAO,CAAC,KAAK,OAAO,IAAI,CAAC;AAAA,IAC7B;AACA,WAAO,oBAAoB,MAAM,CAAC;AAAA,EACpC;AACA,SAAO;AACT;AACA,SAAS,4BAA4B,MAAM,SAAS;AAClD,QAAM,SAAS,QAAQ,IAAI,CAAC,MAAM,CAAC;AACnC,aAAW,KAAK,MAAM;AACpB,UAAM,SAAS,IAAI,OAAO,MAAK;AAC/B,WAAO,KAAK,CAAC;AACb,YAAQ,QAAQ,CAAC,MAAM,MAAM,OAAO,CAAC,KAAK,oBAAoB,MAAM,MAAM,CAAC;AAAA,EAC7E;AACA,SAAO;AACT;AACA,SAAS,oBAAoB,GAAG,GAAG;AACjC,MAAI,MAAM,MAAM,KAAK,MAAM,MAAM;AAC/B,UAAM,IAAI,WAAW,mBAAmB;AAC1C,MAAI,IAAI;AACR,WAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,QAAI,KAAK,KAAK,MAAM,KAAK;AACzB,UAAM,MAAM,IAAI,KAAK;AAAA,EACvB;AACA,SAAO;AACT;AACA,SAAS,eAAe,MAAM,KAAK,aAAa,GAAG,aAAa,IAAI,OAAO,IAAI,WAAW,MAAM;AAC9F,MAAI,EAAE,eAAe,cAAc,cAAc,cAAc,cAAc,gBAAgB,OAAO,MAAM,OAAO,GAAG;AAClH,UAAM,IAAI,WAAW,eAAe;AAAA,EACtC;AACA,MAAI;AACJ,MAAI;AACJ,OAAK,UAAU,cAAc,WAAW;AACtC,UAAM,oBAAoB,oBAAoB,SAAS,GAAG,IAAI;AAC9D,UAAM,WAAW,aAAa,MAAM,OAAO;AAC3C,QAAI,YAAY,mBAAmB;AACjC,qBAAe;AACf;AAAA,IACF;AACA,QAAI,WAAW;AACb,YAAM,IAAI,WAAW,eAAe;AAAA,EACxC;AACA,aAAW,UAAU,CAAC,QAAQ,UAAU,IAAI,GAAG;AAC7C,QAAI,YAAY,gBAAgB,oBAAoB,SAAS,MAAM,IAAI;AACrE,YAAM;AAAA,EACV;AACA,QAAM,KAAK,CAAA;AACX,aAAW,OAAO,MAAM;AACtB,eAAW,IAAI,KAAK,CAAC,GAAG,GAAG,EAAE;AAC7B,eAAW,IAAI,UAAU,iBAAiB,IAAI,MAAM,OAAO,GAAG,EAAE;AAChE,eAAW,KAAK,IAAI,QAAO;AACzB,SAAG,KAAK,CAAC;AAAA,EACb;AACA,QAAM,mBAAmB,oBAAoB,SAAS,GAAG,IAAI;AAC7D,aAAW,GAAG,KAAK,IAAI,GAAG,mBAAmB,GAAG,MAAM,GAAG,EAAE;AAC3D,aAAW,IAAI,IAAI,GAAG,SAAS,KAAK,GAAG,EAAE;AACzC,WAAS,UAAU,KAAK,GAAG,SAAS,kBAAkB,WAAW,MAAM;AACrE,eAAW,SAAS,GAAG,EAAE;AAC3B,QAAM,gBAAgB,MAAM,KAAK,EAAE,QAAQ,KAAK,KAAK,GAAG,SAAS,CAAC,EAAC,GAAI,MAAM,CAAC;AAC9E,KAAG,QAAQ,CAAC,GAAG,MAAM,cAAc,MAAM,CAAC,KAAK,KAAK,KAAK,IAAI,EAAE;AAC/D,SAAO,IAAI,OAAO,SAAS,KAAK,eAAe,IAAI;AACrD;AAEA,SAAS,OAAO,MAAM,SAAS;AAC7B,QAAM;AAAA,IACJ,MAAM;AAAA,IACN,WAAW;AAAA,IACX,aAAa;AAAA,IACb,aAAa;AAAA,IACb,cAAc;AAAA,IACd,SAAS;AAAA,EACb,IAAM,WAAW,CAAA;AACf,QAAM,UAAU,OAAO,SAAS,WAAW,aAAa,IAAI,IAAI,MAAM,QAAQ,IAAI,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI;AAC1G,MAAI,CAAC;AACH,UAAM,IAAI,MAAM,+DAA+D,OAAO,IAAI,EAAE;AAC9F,QAAM,KAAK;AAAA,IACT;AAAA,IACA,OAAO,GAAG;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACJ;AACE,QAAM,SAAS,UAAU;AAAA,IACvB,SAAS,GAAG;AAAA,IACZ,aAAa,GAAG;AAAA,IAChB,MAAM,GAAG;AAAA,IACT,MAAM,GAAG;AAAA,IACT,OAAO,GAAG;AAAA,EACd,GAAK,MAAM;AACT,MAAI,SAAS;AACX,WAAO,OAAO,OAAO,KAAK,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;AAC/D,WAAS,YAAY,MAAM;AAC3B,SAAO;AACT;AACA,SAAS,UAAU,OAAO,SAAS,GAAG;AACpC,MAAI,CAAC;AACH,WAAO;AACT,QAAM,EAAE,KAAI,IAAK;AACjB,QAAM,UAAU,OAAO,SAAS;AAChC,QAAM,OAAO;AACb,QAAM,KAAK,QAAQ,CAAC,QAAQ;AAC1B,aAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,UAAI,QAAQ,KAAK;AACjB,UAAI,KAAK,KAAK;AAAA,IAChB;AAAA,EACF,CAAC;AACD,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,UAAM,KAAK,QAAQ,MAAM,KAAK,EAAE,QAAQ,QAAO,GAAI,CAAC,MAAM,KAAK,CAAC;AAChE,UAAM,KAAK,KAAK,MAAM,KAAK,EAAE,QAAQ,QAAO,GAAI,CAAC,MAAM,KAAK,CAAC;AAAA,EAC/D;AACA,QAAM,IAAI,eAAe;AACzB,QAAM,MAAM,QAAQ,CAAC,QAAQ;AAC3B,aAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,UAAI,QAAQ,CAAC;AACb,UAAI,KAAK,CAAC;AAAA,IACZ;AAAA,EACF,CAAC;AACD,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,UAAM,MAAM,QAAQ,MAAM,KAAK,EAAE,QAAQ,QAAO,GAAI,CAAC,MAAM,CAAC,CAAC;AAC7D,UAAM,MAAM,KAAK,MAAM,KAAK,EAAE,QAAQ,QAAO,GAAI,CAAC,MAAM,CAAC,CAAC;AAAA,EAC5D;AACA,SAAO;AACT;AAsDA,SAAS,WAAW,OAAO;AACzB,SAAO,MAAM,QAAQ,MAAM,OAAO,EAAE,QAAQ,MAAM,QAAQ,EAAE,QAAQ,MAAM,MAAM,EAAE,QAAQ,MAAM,MAAM;AACxG;AACA,SAAS,UAAU,MAAM,UAAU,IAAI;AACrC,QAAM,SAAS,OAAO,MAAM,OAAO;AACnC,QAAM;AAAA,IACJ,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,aAAa;AAAA,EACjB,IAAM;AACJ,QAAM,SAAS,OAAO,OAAO;AAC7B,QAAM,QAAQ,OAAO,OAAO;AAC5B,MAAI,MAAM,wDAAwD,KAAK,IAAI,MAAM;AACjF,QAAM,QAAQ,CAAA;AACd,WAAS,MAAM,GAAG,MAAM,OAAO,MAAM,OAAO;AAC1C,aAAS,MAAM,GAAG,MAAM,OAAO,MAAM,OAAO;AAC1C,YAAM,IAAI,MAAM;AAChB,YAAM,IAAI,MAAM;AAChB,UAAI,OAAO,KAAK,GAAG,EAAE,GAAG;AACtB,cAAM,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,IAAI,SAAS,KAAK,SAAS,GAAG;AAAA,IACpE;AAAA,EACF;AACA,SAAO,eAAe,WAAW,UAAU,CAAC,YAAY,KAAK,aAAa,MAAM;AAChF,SAAO,eAAe,WAAW,UAAU,CAAC,QAAQ,MAAM,KAAK,EAAE,CAAC;AAClE,SAAO;AACP,SAAO;AACT;","x_google_ignoreList":[0]}
@@ -1 +1 @@
1
- {"version":3,"file":"avatar.js","sources":["../../../../../node_modules/.pnpm/@wolffm+prefs-client@1.1.7_react@19.2.8_zod@4.6.7/node_modules/@wolffm/prefs-client/dist/avatar.js"],"sourcesContent":["// src/constants.ts\nvar PREFS_API_BASE = \"https://hadoku.me/prefs\";\n\n// src/avatar-contract.ts\nvar AVATAR_SOURCES = [\"sprite\", \"discord\", \"steam\", \"upload\"];\nvar LINK_PROVIDERS = [\"discord\", \"steam\"];\nvar LINK_MESSAGE_TYPE = \"hadoku-avatar-link\";\nvar RESOLVE_MAX_IDS = 100;\nvar SPRITE_ID_PATTERN = /^[a-z][a-z0-9-]{0,31}$/;\nvar LINK_CALLBACK_PATH = \"/account/link/callback\";\n\n// src/avatar.ts\nvar LINK_WINDOW_NAME = \"hadoku-avatar-link\";\nvar LINK_POPUP_MARK = \"hadoku-avatar-link-popup\";\nfunction markPopup(on) {\n try {\n if (on) sessionStorage.setItem(LINK_POPUP_MARK, \"1\");\n else sessionStorage.removeItem(LINK_POPUP_MARK);\n } catch {\n }\n}\nvar AvatarError = class extends Error {\n constructor(status, message) {\n super(message);\n this.status = status;\n this.name = \"AvatarError\";\n }\n status;\n};\nasync function readJson(res) {\n if (!res.ok) {\n const body = await res.json().catch(() => null);\n throw new AvatarError(res.status, body?.message ?? `HTTP ${res.status}`);\n }\n return await res.json();\n}\nfunction createAvatarClient(opts = {}) {\n const base = `${opts.baseUrl ?? PREFS_API_BASE}/api/v1/_avatar`;\n const f = opts.fetch ?? fetch;\n const call = (path, init = {}) => f(`${base}${path}`, { credentials: \"include\", ...init }).then(readJson);\n const send = (path, method, body) => call(path, {\n method,\n ...body === void 0 ? {} : { headers: { \"Content-Type\": \"application/json\" }, body: JSON.stringify(body) }\n });\n const getSettings = () => call(\"\");\n async function linkInPopup(provider) {\n markPopup(true);\n const popup = window.open(\"about:blank\", LINK_WINDOW_NAME, \"popup,width=520,height=760\");\n markPopup(false);\n if (!popup)\n throw new AvatarError(0, \"The sign-in window was blocked: allow pop-ups for hadoku.me\");\n let authorizeUrl;\n try {\n ({ authorizeUrl } = await send(`/link/${provider}`, \"POST\", {}));\n } catch (err) {\n popup.close();\n throw err;\n }\n popup.location.href = authorizeUrl;\n return new Promise((resolve, reject) => {\n const channel = new BroadcastChannel(LINK_MESSAGE_TYPE);\n let settled = false;\n const finish = (failure) => {\n if (settled) return;\n settled = true;\n channel.close();\n clearInterval(closedPoll);\n clearTimeout(giveUp);\n if (failure) reject(new AvatarError(400, failure));\n else getSettings().then(resolve, reject);\n };\n channel.onmessage = (e) => {\n if (e.data?.type !== LINK_MESSAGE_TYPE) return;\n finish(e.data.ok ? void 0 : e.data.error);\n };\n const closedPoll = setInterval(() => {\n if (!popup.closed) return;\n clearInterval(closedPoll);\n setTimeout(() => finish(), 1500);\n }, 500);\n const giveUp = setTimeout(() => finish(), 10 * 60 * 1e3);\n });\n }\n return {\n /** The caller's settings, including the resolved avatar. */\n get: getSettings,\n /** Pick a source. 409 when it is not available (not linked, nothing uploaded). */\n choose: (source) => send(\"\", \"PUT\", { source }),\n /** Set the source, the character, or both in one write. */\n update: (u) => send(\"\", \"PUT\", u),\n /**\n * Begin linking. Navigate the browser to the returned URL; the provider\n * returns it to hadoku.me/account/link/callback, which completes the link.\n * Call this only from the user's own click: nothing is fetched from\n * Discord or Steam before they ask.\n */\n startLink: (provider) => send(`/link/${provider}`, \"POST\", {}),\n /**\n * Link in a popup, so the page never navigates. Call it straight from the\n * click handler: the window is opened before the first await, which is\n * what popup blockers allow. Resolves with fresh settings once the popup\n * reports back or is closed (closing is not an error: the settings say\n * whether the link landed). Rejects only when the popup could not open\n * or the link could not start.\n */\n linkInPopup: (provider) => linkInPopup(provider),\n /** Finish a link from the callback page's query string (`location.search`). */\n completeLink: (query) => send(\"/link/complete\", \"POST\", { query: query.replace(/^\\?/, \"\") }),\n /** Delete the linked id and its cached avatar URL. */\n unlink: (provider) => send(`/link/${provider}`, \"DELETE\"),\n /** Upload an image (PNG, JPEG, WebP or GIF). It is re-encoded and becomes the chosen source. */\n upload: (image) => call(\"/upload\", { method: \"POST\", body: image }),\n removeUpload: () => send(\"/upload\", \"DELETE\")\n };\n}\nasync function resolveAvatars(opts, userIds) {\n const f = opts.fetch ?? fetch;\n const url = `${opts.baseUrl ?? PREFS_API_BASE}/api/v1/_avatar/resolve`;\n const unique = [...new Set(userIds)];\n const out = {};\n for (let i = 0; i < unique.length; i += RESOLVE_MAX_IDS) {\n const res = await f(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"X-User-Key\": opts.serviceKey },\n body: JSON.stringify({ userIds: unique.slice(i, i + RESOLVE_MAX_IDS) })\n });\n Object.assign(out, (await readJson(res)).avatars);\n }\n return out;\n}\nexport {\n AVATAR_SOURCES,\n AvatarError,\n LINK_CALLBACK_PATH,\n LINK_MESSAGE_TYPE,\n LINK_POPUP_MARK,\n LINK_PROVIDERS,\n RESOLVE_MAX_IDS,\n SPRITE_ID_PATTERN,\n createAvatarClient,\n resolveAvatars\n};\n"],"names":[],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"avatar.js","sources":["../../../../../node_modules/.pnpm/@wolffm+prefs-client@1.1.8_react@19.2.8_zod@4.6.7/node_modules/@wolffm/prefs-client/dist/avatar.js"],"sourcesContent":["// src/constants.ts\nvar PREFS_API_BASE = \"https://hadoku.me/prefs\";\n\n// src/avatar-contract.ts\nvar AVATAR_SOURCES = [\"sprite\", \"discord\", \"steam\", \"upload\"];\nvar LINK_PROVIDERS = [\"discord\", \"steam\"];\nvar LINK_MESSAGE_TYPE = \"hadoku-avatar-link\";\nvar RESOLVE_MAX_IDS = 100;\nvar SPRITE_ID_PATTERN = /^[a-z][a-z0-9-]{0,31}$/;\nvar LINK_CALLBACK_PATH = \"/account/link/callback\";\n\n// src/avatar.ts\nvar LINK_WINDOW_NAME = \"hadoku-avatar-link\";\nvar LINK_POPUP_MARK = \"hadoku-avatar-link-popup\";\nfunction markPopup(on) {\n try {\n if (on) sessionStorage.setItem(LINK_POPUP_MARK, \"1\");\n else sessionStorage.removeItem(LINK_POPUP_MARK);\n } catch {\n }\n}\nvar AvatarError = class extends Error {\n constructor(status, message) {\n super(message);\n this.status = status;\n this.name = \"AvatarError\";\n }\n status;\n};\nasync function readJson(res) {\n if (!res.ok) {\n const body = await res.json().catch(() => null);\n throw new AvatarError(res.status, body?.message ?? `HTTP ${res.status}`);\n }\n return await res.json();\n}\nfunction createAvatarClient(opts = {}) {\n const base = `${opts.baseUrl ?? PREFS_API_BASE}/api/v1/_avatar`;\n const f = opts.fetch ?? fetch;\n const call = (path, init = {}) => f(`${base}${path}`, { credentials: \"include\", ...init }).then(readJson);\n const send = (path, method, body) => call(path, {\n method,\n ...body === void 0 ? {} : { headers: { \"Content-Type\": \"application/json\" }, body: JSON.stringify(body) }\n });\n const getSettings = () => call(\"\");\n async function linkInPopup(provider) {\n markPopup(true);\n const popup = window.open(\"about:blank\", LINK_WINDOW_NAME, \"popup,width=520,height=760\");\n markPopup(false);\n if (!popup)\n throw new AvatarError(0, \"The sign-in window was blocked: allow pop-ups for hadoku.me\");\n let authorizeUrl;\n try {\n ({ authorizeUrl } = await send(`/link/${provider}`, \"POST\", {}));\n } catch (err) {\n popup.close();\n throw err;\n }\n popup.location.href = authorizeUrl;\n return new Promise((resolve, reject) => {\n const channel = new BroadcastChannel(LINK_MESSAGE_TYPE);\n let settled = false;\n const finish = (failure) => {\n if (settled) return;\n settled = true;\n channel.close();\n clearInterval(closedPoll);\n clearTimeout(giveUp);\n if (failure) reject(new AvatarError(400, failure));\n else getSettings().then(resolve, reject);\n };\n channel.onmessage = (e) => {\n if (e.data?.type !== LINK_MESSAGE_TYPE) return;\n finish(e.data.ok ? void 0 : e.data.error);\n };\n const closedPoll = setInterval(() => {\n if (!popup.closed) return;\n clearInterval(closedPoll);\n setTimeout(() => finish(), 1500);\n }, 500);\n const giveUp = setTimeout(() => finish(), 10 * 60 * 1e3);\n });\n }\n return {\n /** The caller's settings, including the resolved avatar. */\n get: getSettings,\n /** Pick a source. 409 when it is not available (not linked, nothing uploaded). */\n choose: (source) => send(\"\", \"PUT\", { source }),\n /** Set the source, the character, or both in one write. */\n update: (u) => send(\"\", \"PUT\", u),\n /**\n * Begin linking. Navigate the browser to the returned URL; the provider\n * returns it to hadoku.me/account/link/callback, which completes the link.\n * Call this only from the user's own click: nothing is fetched from\n * Discord or Steam before they ask.\n */\n startLink: (provider) => send(`/link/${provider}`, \"POST\", {}),\n /**\n * Link in a popup, so the page never navigates. Call it straight from the\n * click handler: the window is opened before the first await, which is\n * what popup blockers allow. Resolves with fresh settings once the popup\n * reports back or is closed (closing is not an error: the settings say\n * whether the link landed). Rejects only when the popup could not open\n * or the link could not start.\n */\n linkInPopup: (provider) => linkInPopup(provider),\n /** Finish a link from the callback page's query string (`location.search`). */\n completeLink: (query) => send(\"/link/complete\", \"POST\", { query: query.replace(/^\\?/, \"\") }),\n /** Delete the linked id and its cached avatar URL. */\n unlink: (provider) => send(`/link/${provider}`, \"DELETE\"),\n /** Upload an image (PNG, JPEG, WebP or GIF). It is re-encoded and becomes the chosen source. */\n upload: (image) => call(\"/upload\", { method: \"POST\", body: image }),\n removeUpload: () => send(\"/upload\", \"DELETE\")\n };\n}\nasync function resolveAvatars(opts, userIds) {\n const f = opts.fetch ?? fetch;\n const url = `${opts.baseUrl ?? PREFS_API_BASE}/api/v1/_avatar/resolve`;\n const unique = [...new Set(userIds)];\n const out = {};\n for (let i = 0; i < unique.length; i += RESOLVE_MAX_IDS) {\n const res = await f(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"X-User-Key\": opts.serviceKey },\n body: JSON.stringify({ userIds: unique.slice(i, i + RESOLVE_MAX_IDS) })\n });\n Object.assign(out, (await readJson(res)).avatars);\n }\n return out;\n}\nexport {\n AVATAR_SOURCES,\n AvatarError,\n LINK_CALLBACK_PATH,\n LINK_MESSAGE_TYPE,\n LINK_POPUP_MARK,\n LINK_PROVIDERS,\n RESOLVE_MAX_IDS,\n SPRITE_ID_PATTERN,\n createAvatarClient,\n resolveAvatars\n};\n"],"names":[],"mappings":"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","x_google_ignoreList":[0]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hadoku/task-ui-components",
3
- "version": "4.22.7",
3
+ "version": "4.23.1",
4
4
  "description": "Reusable UI components with Bento grid and metallic gradient support",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -33,6 +33,12 @@ import React, { useCallback, useEffect, useId, useRef, useState } from 'react'
33
33
  import { useSettingsTab } from '@wolffm/themes'
34
34
  import { SettingsIcon } from './ThemeIcons'
35
35
  import { AvatarPicker } from './AvatarPicker'
36
+
37
+ // A grantee's own service credentials, with a QR encoder for TOTP enrolment:
38
+ // its own chunk, fetched only when a grantee opens it.
39
+ const ServiceAccess = React.lazy(() =>
40
+ import('./ServiceAccess').then(m => ({ default: m.ServiceAccess }))
41
+ )
36
42
  import {
37
43
  deleteOwnAccount,
38
44
  prefetchSettings,
@@ -261,6 +267,9 @@ export function ConnectedSettings({
261
267
 
262
268
  // Avatar: the picker loads only when opened, never at mount (AvatarPicker).
263
269
  const [avatarOpen, setAvatarOpen] = useState(false)
270
+ // Service identities this person may mint for (whoami.serviceGrants).
271
+ const [serviceGrants, setServiceGrants] = useState(0)
272
+ const [serviceOpen, setServiceOpen] = useState(false)
264
273
 
265
274
  // Content level
266
275
  const [content, setContent] = useState<ContentLevelState | null>(null)
@@ -378,9 +387,10 @@ export function ConnectedSettings({
378
387
  useEffect(() => {
379
388
  let live = true
380
389
  prefetchSettings({ userType: userTypeProp, name: nameProp })
381
- .then(({ identity, content: state, passkeys }) => {
390
+ .then(({ identity, content: state, passkeys, serviceGrants: grants }) => {
382
391
  if (!live) return
383
392
  setPasskeyCount(passkeys)
393
+ setServiceGrants(grants)
384
394
  // Props stay authoritative: the host passed them because it can see an
385
395
  // identity this component can't resolve for itself.
386
396
  if (userTypeProp === undefined) {
@@ -720,6 +730,31 @@ export function ConnectedSettings({
720
730
  {avatarOpen && <AvatarPicker />}
721
731
  </section>
722
732
  )}
733
+
734
+ {/* Service access: only for someone the operator granted a
735
+ service identity. Collapsed until Open, like Avatar. */}
736
+ {!resolving && serviceGrants > 0 && (
737
+ <section className="settings-popout__row settings-popout__row--stack">
738
+ <span className="settings-popout__inline">
739
+ <span className="settings-popout__label settings-popout__label--grow">
740
+ Service access
741
+ </span>
742
+ <button
743
+ type="button"
744
+ className="settings-popout__btn"
745
+ aria-expanded={serviceOpen}
746
+ onClick={() => setServiceOpen(v => !v)}
747
+ >
748
+ {serviceOpen ? 'Done' : 'Open'}
749
+ </button>
750
+ </span>
751
+ {serviceOpen && (
752
+ <React.Suspense fallback={<span className="settings-popout__hint">…</span>}>
753
+ <ServiceAccess />
754
+ </React.Suspense>
755
+ )}
756
+ </section>
757
+ )}
723
758
  </>
724
759
  )}
725
760
 
@@ -0,0 +1,279 @@
1
+ import React, { useCallback, useEffect, useState } from 'react'
2
+ import { renderSVG } from 'uqr'
3
+ import { loadSignInClient, type PasskeyAssertion } from '../lib/settingsClient'
4
+
5
+ /**
6
+ * Service access: a grantee's own credentials for the service identities the
7
+ * operator granted them (hadoku_site docs/planning/service-grants-2026-10-31.md).
8
+ *
9
+ * Two steps, both behind a fresh passkey tap:
10
+ * 1. enrol an authenticator app once (the QR is shown once, then confirmed
11
+ * with one code);
12
+ * 2. mint a credential: passkey tap + a current code. The key is shown once
13
+ * and lives 7 days.
14
+ *
15
+ * Loaded only when opened (React.lazy in ConnectedSettings), so the QR encoder
16
+ * costs a grantee one chunk and everyone else nothing.
17
+ */
18
+
19
+ const BASE = '/session/service-access'
20
+
21
+ interface Grant {
22
+ identityUserId: string
23
+ name: string | null
24
+ }
25
+
26
+ interface Credential {
27
+ prefix: string
28
+ identityUserId: string
29
+ name: string | null
30
+ expiresAt: number | null
31
+ lastSeenAt: number
32
+ live: boolean
33
+ }
34
+
35
+ interface State {
36
+ grants: Grant[]
37
+ totp: 'none' | 'pending' | 'active'
38
+ credentials: Credential[]
39
+ }
40
+
41
+ const S = {
42
+ stack: { display: 'flex', flexDirection: 'column', gap: 8 },
43
+ line: { display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' },
44
+ grow: { flex: 1, minWidth: 0 },
45
+ mono: { fontFamily: 'ui-monospace, monospace', fontSize: '0.75rem', wordBreak: 'break-all' },
46
+ code: { width: '7ch', fontFamily: 'ui-monospace, monospace', letterSpacing: '0.1em' },
47
+ qr: { width: 168, height: 168 }
48
+ } satisfies Record<string, React.CSSProperties>
49
+
50
+ async function call<T>(path: string, body?: unknown): Promise<T> {
51
+ const res = await fetch(`${BASE}${path}`, {
52
+ method: body === undefined ? 'GET' : 'POST',
53
+ credentials: 'same-origin',
54
+ headers: body === undefined ? undefined : { 'Content-Type': 'application/json' },
55
+ body: body === undefined ? undefined : JSON.stringify(body)
56
+ })
57
+ const data = (await res.json().catch(() => ({}))) as T & { error?: string }
58
+ if (!res.ok) throw new Error(data.error ?? `HTTP ${res.status}`)
59
+ return data
60
+ }
61
+
62
+ async function stepUp(): Promise<PasskeyAssertion> {
63
+ const client = await loadSignInClient()
64
+ if (!client?.stepUpPasskey) throw new Error('Passkeys unavailable here')
65
+ return client.stepUpPasskey()
66
+ }
67
+
68
+ function left(expiresAt: number | null): string {
69
+ if (expiresAt === null) return ''
70
+ const h = Math.floor((expiresAt - Date.now()) / 3_600_000)
71
+ return h >= 24 ? `${Math.floor(h / 24)}d left` : h >= 1 ? `${h}h left` : 'under 1h left'
72
+ }
73
+
74
+ const message = (err: unknown) => (err instanceof Error ? err.message : String(err))
75
+
76
+ export function ServiceAccess() {
77
+ const [state, setState] = useState<State | null>(null)
78
+ const [error, setError] = useState<string | null>(null)
79
+ const [busy, setBusy] = useState(false)
80
+ const [enrol, setEnrol] = useState<{ uri: string; secret: string } | null>(null)
81
+ const [code, setCode] = useState('')
82
+ const [minted, setMinted] = useState<{ key: string; name: string; expiresAt: number } | null>(
83
+ null
84
+ )
85
+
86
+ const load = useCallback(async () => {
87
+ setState(await call<State>(''))
88
+ }, [])
89
+
90
+ useEffect(() => {
91
+ load().catch((err: unknown) => setError(message(err)))
92
+ }, [load])
93
+
94
+ const run = async (work: () => Promise<void>) => {
95
+ setBusy(true)
96
+ setError(null)
97
+ try {
98
+ await work()
99
+ } catch (err) {
100
+ setError(message(err))
101
+ } finally {
102
+ setBusy(false)
103
+ }
104
+ }
105
+
106
+ if (!state) {
107
+ return (
108
+ <span className="settings-popout__hint" role={error ? 'alert' : undefined}>
109
+ {error ?? '…'}
110
+ </span>
111
+ )
112
+ }
113
+
114
+ const codeOk = /^\d{6}$/.test(code)
115
+ const codeInput = (
116
+ <input
117
+ value={code}
118
+ onChange={e => setCode(e.target.value.replace(/\D/g, '').slice(0, 6))}
119
+ inputMode="numeric"
120
+ autoComplete="one-time-code"
121
+ placeholder="123456"
122
+ aria-label="Authenticator code"
123
+ className="settings-popout__input"
124
+ style={S.code}
125
+ />
126
+ )
127
+
128
+ return (
129
+ <div style={S.stack}>
130
+ {state.totp !== 'active' && !enrol && (
131
+ <span style={S.line}>
132
+ <span className="settings-popout__label" style={S.grow}>
133
+ Authenticator
134
+ </span>
135
+ <button
136
+ type="button"
137
+ className="settings-popout__btn settings-popout__btn--primary"
138
+ disabled={busy}
139
+ onClick={() => {
140
+ run(async () => {
141
+ setEnrol(
142
+ await call<{ uri: string; secret: string }>('/totp/start', {
143
+ assertion: await stepUp()
144
+ })
145
+ )
146
+ }).catch(console.error)
147
+ }}
148
+ >
149
+ Set up
150
+ </button>
151
+ </span>
152
+ )}
153
+
154
+ {enrol && (
155
+ <div style={S.stack}>
156
+ <span
157
+ role="img"
158
+ aria-label="Authenticator QR code"
159
+ style={S.qr}
160
+ dangerouslySetInnerHTML={{ __html: renderSVG(enrol.uri) }}
161
+ />
162
+ <span style={S.mono}>{enrol.secret}</span>
163
+ <span style={S.line}>
164
+ {codeInput}
165
+ <button
166
+ type="button"
167
+ className="settings-popout__btn settings-popout__btn--primary"
168
+ disabled={busy || !codeOk}
169
+ onClick={() => {
170
+ run(async () => {
171
+ await call('/totp/confirm', { code })
172
+ setEnrol(null)
173
+ setCode('')
174
+ await load()
175
+ }).catch(console.error)
176
+ }}
177
+ >
178
+ Confirm
179
+ </button>
180
+ </span>
181
+ </div>
182
+ )}
183
+
184
+ {minted && (
185
+ <div style={S.stack}>
186
+ <span className="settings-popout__label">
187
+ {minted.name} · shown once · {left(minted.expiresAt)}
188
+ </span>
189
+ <span style={S.mono}>{minted.key}</span>
190
+ <span style={S.line}>
191
+ <button
192
+ type="button"
193
+ className="settings-popout__btn"
194
+ onClick={() => {
195
+ navigator.clipboard.writeText(minted.key).catch(console.error)
196
+ }}
197
+ >
198
+ Copy
199
+ </button>
200
+ <button type="button" className="settings-popout__btn" onClick={() => setMinted(null)}>
201
+ Hide
202
+ </button>
203
+ </span>
204
+ </div>
205
+ )}
206
+
207
+ {state.totp === 'active' && (
208
+ <span style={S.line}>
209
+ <span className="settings-popout__label" style={S.grow}>
210
+ Code
211
+ </span>
212
+ {codeInput}
213
+ </span>
214
+ )}
215
+
216
+ {state.totp === 'active' &&
217
+ state.grants.map(g => (
218
+ <span key={g.identityUserId} style={S.line}>
219
+ <span className="settings-popout__label" style={{ ...S.grow, ...S.mono }}>
220
+ {g.name ?? g.identityUserId}
221
+ </span>
222
+ <button
223
+ type="button"
224
+ className="settings-popout__btn settings-popout__btn--primary"
225
+ disabled={busy || !codeOk}
226
+ onClick={() => {
227
+ run(async () => {
228
+ const assertion = await stepUp()
229
+ const out = await call<{ key: string; name: string; expiresAt: number }>(
230
+ '/mint',
231
+ {
232
+ identityUserId: g.identityUserId,
233
+ assertion,
234
+ totp: code
235
+ }
236
+ )
237
+ setCode('')
238
+ setMinted(out)
239
+ await load()
240
+ }).catch(console.error)
241
+ }}
242
+ >
243
+ Mint
244
+ </button>
245
+ </span>
246
+ ))}
247
+
248
+ {state.credentials
249
+ .filter(c => c.live)
250
+ .map(c => (
251
+ <span key={c.prefix} style={S.line}>
252
+ <span style={{ ...S.grow, ...S.mono }}>
253
+ {c.prefix}… {c.name}
254
+ </span>
255
+ <span className="settings-popout__hint">{left(c.expiresAt)}</span>
256
+ <button
257
+ type="button"
258
+ className="settings-popout__btn"
259
+ disabled={busy}
260
+ onClick={() => {
261
+ run(async () => {
262
+ await call('/revoke', { prefix: c.prefix })
263
+ await load()
264
+ }).catch(console.error)
265
+ }}
266
+ >
267
+ Revoke
268
+ </button>
269
+ </span>
270
+ ))}
271
+
272
+ {error && (
273
+ <span className="settings-popout__error" role="alert">
274
+ {error}
275
+ </span>
276
+ )}
277
+ </div>
278
+ )
279
+ }
@@ -56,6 +56,10 @@ const WHOAMI_GLOBAL = '__hadokuWhoami'
56
56
  *
57
57
  * `passkeys` (edge-router ≥ 2026-10-28) counts the passkeys that sign this
58
58
  * session in. Absent means unknown, never none.
59
+ *
60
+ * `serviceGrants` (edge-router ≥ 2026-10-31) counts the service identities
61
+ * this person may mint their own credentials for; Service access shows only
62
+ * above zero.
59
63
  */
60
64
  interface WhoamiBody {
61
65
  valid?: boolean
@@ -64,6 +68,7 @@ interface WhoamiBody {
64
68
  contentLevel?: number
65
69
  maxContentLevel?: number
66
70
  passkeys?: number
71
+ serviceGrants?: number
67
72
  }
68
73
 
69
74
  // Hard timeout on every settings request. Without it, a request throttled by
@@ -293,6 +298,17 @@ export interface SignInClient {
293
298
  signInWithPasskey?: (opts?: { signal?: AbortSignal }) => Promise<SignInResult>
294
299
  /** Saves a passkey for the signed-in person on this device. Throws Error(message). */
295
300
  addPasskey?: (opts?: { signal?: AbortSignal }) => Promise<{ saved: boolean; passkeys: number }>
301
+ /** A fresh passkey tap from the signed-in person; the assertion to post. Throws Error(message). */
302
+ stepUpPasskey?: (opts?: { signal?: AbortSignal }) => Promise<PasskeyAssertion>
303
+ }
304
+
305
+ /** What `stepUpPasskey` resolves to: the WebAuthn assertion, base64url fields. */
306
+ export interface PasskeyAssertion {
307
+ id: string
308
+ clientDataJSON: string
309
+ authenticatorData: string
310
+ signature: string
311
+ userHandle: string | null
296
312
  }
297
313
 
298
314
  export function loadSignInClient(): Promise<SignInClient | null> {
@@ -308,6 +324,10 @@ export function loadSignInClient(): Promise<SignInClient | null> {
308
324
  addPasskey:
309
325
  typeof m.addPasskey === 'function'
310
326
  ? (m.addPasskey as SignInClient['addPasskey'])
327
+ : undefined,
328
+ stepUpPasskey:
329
+ typeof m.stepUpPasskey === 'function'
330
+ ? (m.stepUpPasskey as SignInClient['stepUpPasskey'])
311
331
  : undefined
312
332
  }
313
333
  : null,
@@ -353,6 +373,8 @@ export interface SettingsSnapshot {
353
373
  content: ContentLevelState | null
354
374
  /** Passkeys that sign this person in; null = unknown (older edge, host-supplied identity). */
355
375
  passkeys: number | null
376
+ /** Service identities this person may mint for; 0 when unknown. */
377
+ serviceGrants: number
356
378
  }
357
379
 
358
380
  /** Identity the host already knows, so we don't ask the server for it again. */
@@ -432,7 +454,12 @@ async function resolveSettings(hints: SettingsPrefetchHints): Promise<SettingsSn
432
454
  contentPromise,
433
455
  bodyPromise
434
456
  ])
435
- return { identity, content, passkeys: passkeysFromWhoami(body) }
457
+ return {
458
+ identity,
459
+ content,
460
+ passkeys: passkeysFromWhoami(body),
461
+ serviceGrants: body?.valid && typeof body.serviceGrants === 'number' ? body.serviceGrants : 0
462
+ }
436
463
  }
437
464
 
438
465
  function passkeysFromWhoami(body: WhoamiBody | null): number | null {