diff --git a/docs/components/mdx/CodeTabs.jsx b/docs/components/mdx/CodeTabs.jsx index dd3c6fbc3f7e8..b20269df0b2b5 100644 --- a/docs/components/mdx/CodeTabs.jsx +++ b/docs/components/mdx/CodeTabs.jsx @@ -1,6 +1,6 @@ 'use client' -import React, { useState, useEffect, useRef, useCallback } from 'react' +import React, { useState, useEffect, useLayoutEffect, useRef, useCallback } from 'react' import styles from './CodeTabs.module.css' const langs = { @@ -23,6 +23,7 @@ const PREFERRED_LANGS = ['yaml', 'python'] export const CodeTabs = ({ children }) => { const containerRef = useRef(null) + const scrollAnchorRef = useRef(null) const [codeBlocks, setCodeBlocks] = useState([]) const [selectedTab, setSelectedTab] = useState(null) const [isInitialized, setIsInitialized] = useState(false) @@ -99,7 +100,7 @@ export const CodeTabs = ({ children }) => { }, [codeBlocks, isInitialized]) // Update visibility of code blocks based on selected tab - useEffect(() => { + useLayoutEffect(() => { if (!containerRef.current || !selectedTab || codeBlocks.length === 0) return codeBlocks.forEach((block) => { @@ -107,6 +108,16 @@ export const CodeTabs = ({ children }) => { block.wrapper.style.display = block.lang === selectedTab ? 'block' : 'none' } }) + + // Correct scroll when tab heights change across synced CodeTabs instances + if (scrollAnchorRef.current) { + const newTop = containerRef.current.getBoundingClientRect().top + const delta = newTop - scrollAnchorRef.current + if (delta !== 0) { + window.scrollBy(0, delta) + } + scrollAnchorRef.current = null + } }, [selectedTab, codeBlocks]) // Get unique languages maintaining order @@ -123,6 +134,10 @@ export const CodeTabs = ({ children }) => { const handleTabClick = useCallback((lang) => { if (lang !== selectedTab) { + if (containerRef.current) { + scrollAnchorRef.current = containerRef.current.getBoundingClientRect().top + } + if (lang === 'python' || lang === 'javascript' || lang === 'yaml') { localStorage.setItem(STORAGE_KEY, lang) window.dispatchEvent( diff --git a/docs/content/cube-core-logo.png b/docs/content/cube-core-logo.png new file mode 100644 index 0000000000000..2132bf291a841 Binary files /dev/null and b/docs/content/cube-core-logo.png differ diff --git a/docs/content/product/data-modeling/reference/types-and-formats.mdx b/docs/content/product/data-modeling/reference/types-and-formats.mdx index ff394b4b86b6f..e6011881eb927 100644 --- a/docs/content/product/data-modeling/reference/types-and-formats.mdx +++ b/docs/content/product/data-modeling/reference/types-and-formats.mdx @@ -624,6 +624,100 @@ cubes: +### Custom numeric formats + +Measures with numeric types support custom formatting +using [d3-format][link-d3-format] specifier strings. + + + +Custom numeric formatting is subject to support in [visualization tools][ref-viz-tools]. +Check [APIs & Integrations][ref-apis-support] for details. + + + + + +```javascript +cube(`orders`, { + // ... + + measures: { + total_amount: { + sql: `amount`, + type: `sum`, + format: `$,.2f` + } + } +}) +``` + +```yaml +cubes: + - name: orders + # ... + + measures: + - name: total_amount + sql: amount + type: sum + format: "$,.2f" +``` + + + +#### Common format examples + +| Format string | Description | Example output | +|---------------|-------------|----------------| +| `.2f` | Fixed-point, 2 decimal places | 1234.57 | +| `,.0f` | Grouped thousands, no decimals | 1,235 | +| `$,.2f` | Currency with grouped thousands | $1,234.57 | +| `.0%` | Percentage, no decimals | 12% | +| `.2s` | SI prefix, 2 significant digits | 1.2k | +| `+.2f` | Explicit sign, 2 decimal places | +1234.57 | +| `.2~f` | Trimmed trailing zeros, 2 decimals | 1234.5 | + +#### Format specifier syntax + +The full syntax for a d3-format specifier is: + +``` +[[fill]align][sign][symbol][0][width][,][.precision][~][type] +``` + +| Component | Description | +|-----------|-------------| +| `fill` | Character to use for padding | +| `align` | `>` (right), `<` (left), `^` (center), `=` (pad after sign) | +| `sign` | `-` (negative only, default), `+` (positive and negative), `(` (parentheses for negative) | +| `symbol` | `$` (currency prefix), `#` (alternate form for binary/octal/hex) | +| `0` | Enable zero-padding (shorthand for `fill=0` with `align==`) | +| `width` | Minimum field width | +| `,` | Enable comma grouping separator | +| `.precision` | Number of digits after the decimal point (for `f`, `%`) or significant digits (for other types) | +| `~` | Trim trailing zeros | +| `type` | Output format type (see table below) | + +#### Supported type characters + +| Type | Description | +|------|-------------| +| `f` | Fixed-point notation | +| `e` | Exponent notation | +| `g` | Either decimal or exponent notation, rounded to significant digits | +| `r` | Decimal notation, rounded to significant digits | +| `s` | Decimal notation with an SI prefix, rounded to significant digits | +| `%` | Multiply by 100 and format with `f`, followed by percent sign | +| `p` | Multiply by 100, round to significant digits, followed by percent sign | +| `d` | Integer; ignores non-integer values | +| `b` | Binary | +| `o` | Octal | +| `x` | Hexadecimal (lowercase) | +| `X` | Hexadecimal (uppercase) | +| `c` | Character data (converts integer to Unicode) | +| (none) | Similar to `g`, but trims trailing zeros | + ## Dimension Types This section describes the various types that can be assigned to a @@ -832,7 +926,7 @@ cubes: When `switch` dimensions are queried or introspected using the [`/v1/meta` REST API -endpoint][ref-meta-api], they are represented as dimensions of type `string`. +endpoint][ref-meta-api], they are represented as dimensions of type `string`. @@ -1073,6 +1167,52 @@ cubes: +### Custom numeric formats + +Dimensions with the `number` type support custom formatting using +[d3-format][link-d3-format] specifier strings. + + + +Custom numeric formatting is subject to support in [visualization tools][ref-viz-tools]. +Check [APIs & Integrations][ref-apis-support] for details. + + + + + +```javascript +cube(`orders`, { + // ... + + dimensions: { + amount: { + sql: `amount`, + type: `number`, + format: `$,.2f` + } + } +}) +``` + +```yaml +cubes: + - name: orders + # ... + + dimensions: + - name: amount + sql: amount + type: number + format: "$,.2f" +``` + + + +See the [Custom numeric formats](#custom-numeric-formats) section under [Measure +Formats](#measure-formats) for the full format specifier syntax and supported +type characters. + ### Custom time formats Dimensions with `time` type support custom formatting using @@ -1179,4 +1319,5 @@ cubes: [ref-meta-api]: /product/apis-integrations/rest-api/reference#base_pathv1meta [ref-explore]: /product/exploration/explore [ref-workbooks]: /product/exploration/workbooks -[ref-dashboards]: /product/presentation/dashboards \ No newline at end of file +[ref-dashboards]: /product/presentation/dashboards +[link-d3-format]: https://d3js.org/d3-format diff --git a/docs/package.json b/docs/package.json index 16e522e3f130b..401ed047950be 100644 --- a/docs/package.json +++ b/docs/package.json @@ -15,7 +15,7 @@ "@radix-ui/react-navigation-menu": "^1.2.14", "algoliasearch": "^5.49.0", "cubedev-tracking": "1.1.0", - "next": "^16.1.6", + "next": "^16.1.7", "nextra": "^4.6.1", "nextra-theme-docs": "^4.6.1", "react": "^19.2.4", diff --git a/docs/yarn.lock b/docs/yarn.lock index ecee9ac22e093..d2ecd3ff8c8c3 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -670,50 +670,50 @@ "@napi-rs/simple-git-win32-ia32-msvc" "0.1.22" "@napi-rs/simple-git-win32-x64-msvc" "0.1.22" -"@next/env@16.1.6": - version "16.1.6" - resolved "https://registry.yarnpkg.com/@next/env/-/env-16.1.6.tgz#0f85979498249a94ef606ef535042a831f905e89" - integrity sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ== - -"@next/swc-darwin-arm64@16.1.6": - version "16.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.1.6.tgz#fbe1e360efdcc9ebd0a10301518275bc59e12a91" - integrity sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw== - -"@next/swc-darwin-x64@16.1.6": - version "16.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-16.1.6.tgz#0e3781ef3abc8251c2a21addc733d9a87f44829b" - integrity sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ== - -"@next/swc-linux-arm64-gnu@16.1.6": - version "16.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.1.6.tgz#b24511af2c6129f2deaf5c8c04d297fe09cd40d7" - integrity sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw== - -"@next/swc-linux-arm64-musl@16.1.6": - version "16.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.1.6.tgz#9d4ed0565689fc6a867250f994736a5b8c542ccb" - integrity sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ== - -"@next/swc-linux-x64-gnu@16.1.6": - version "16.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.1.6.tgz#cc757f4384e7eab7d3dba704a97f737518bae0d2" - integrity sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ== - -"@next/swc-linux-x64-musl@16.1.6": - version "16.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.1.6.tgz#ef1341740f29717deea7c6ec27ae6269386e20d1" - integrity sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg== - -"@next/swc-win32-arm64-msvc@16.1.6": - version "16.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.1.6.tgz#fee8719242aecf9c39c3a66f1f73821f7884dd16" - integrity sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw== - -"@next/swc-win32-x64-msvc@16.1.6": - version "16.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.1.6.tgz#60c27323c30f35722b20fd6d62449fbb768e46d9" - integrity sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A== +"@next/env@16.1.7": + version "16.1.7" + resolved "https://registry.yarnpkg.com/@next/env/-/env-16.1.7.tgz#169482a9a76aab0d9360813df898a88667d79ffc" + integrity sha512-rJJbIdJB/RQr2F1nylZr/PJzamvNNhfr3brdKP6s/GW850jbtR70QlSfFselvIBbcPUOlQwBakexjFzqLzF6pg== + +"@next/swc-darwin-arm64@16.1.7": + version "16.1.7" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.1.7.tgz#6022bec143c23837ca4744fee4ab48b0f74b0faa" + integrity sha512-b2wWIE8sABdyafc4IM8r5Y/dS6kD80JRtOGrUiKTsACFQfWWgUQ2NwoUX1yjFMXVsAwcQeNpnucF2ZrujsBBPg== + +"@next/swc-darwin-x64@16.1.7": + version "16.1.7" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-16.1.7.tgz#3f1604e5a59645a0394b74e50791ff2c477167b8" + integrity sha512-zcnVaaZulS1WL0Ss38R5Q6D2gz7MtBu8GZLPfK+73D/hp4GFMrC2sudLky1QibfV7h6RJBJs/gOFvYP0X7UVlQ== + +"@next/swc-linux-arm64-gnu@16.1.7": + version "16.1.7" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.1.7.tgz#458c98c8b790efa30bc2866f715352ba3cb47cb5" + integrity sha512-2ant89Lux/Q3VyC8vNVg7uBaFVP9SwoK2jJOOR0L8TQnX8CAYnh4uctAScy2Hwj2dgjVHqHLORQZJ2wH6VxhSQ== + +"@next/swc-linux-arm64-musl@16.1.7": + version "16.1.7" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.1.7.tgz#1a6ae4d0894f8751f8951ca0fed6e103e27bfc7a" + integrity sha512-uufcze7LYv0FQg9GnNeZ3/whYfo+1Q3HnQpm16o6Uyi0OVzLlk2ZWoY7j07KADZFY8qwDbsmFnMQP3p3+Ftprw== + +"@next/swc-linux-x64-gnu@16.1.7": + version "16.1.7" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.1.7.tgz#183126cfbf45a96e3b3b37e35b5429e4c48795bd" + integrity sha512-KWVf2gxYvHtvuT+c4MBOGxuse5TD7DsMFYSxVxRBnOzok/xryNeQSjXgxSv9QpIVlaGzEn/pIuI6Koosx8CGWA== + +"@next/swc-linux-x64-musl@16.1.7": + version "16.1.7" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.1.7.tgz#59906d387aa934fc2d066ff6c0ba695ebc904381" + integrity sha512-HguhaGwsGr1YAGs68uRKc4aGWxLET+NevJskOcCAwXbwj0fYX0RgZW2gsOCzr9S11CSQPIkxmoSbuVaBp4Z3dA== + +"@next/swc-win32-arm64-msvc@16.1.7": + version "16.1.7" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.1.7.tgz#e97a31605ca10e5ca493555f840e4972496ce350" + integrity sha512-S0n3KrDJokKTeFyM/vGGGR8+pCmXYrjNTk2ZozOL1C/JFdfUIL9O1ATaJOl5r2POe56iRChbsszrjMAdWSv7kQ== + +"@next/swc-win32-x64-msvc@16.1.7": + version "16.1.7" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.1.7.tgz#eeaf9fb75de437232e1c8b46d16d1ba8b0c635c2" + integrity sha512-mwgtg8CNZGYm06LeEd+bNnOUfwOyNem/rOiP14Lsz+AnUY92Zq/LXwtebtUiaeVkhbroRCQ0c8GlR4UT1U+0yg== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -1471,10 +1471,10 @@ balanced-match@^4.0.2: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-4.0.3.tgz#6337a2f23e0604a30481423432f99eac603599f9" integrity sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g== -baseline-browser-mapping@^2.8.3: - version "2.9.19" - resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz#3e508c43c46d961eb4d7d2e5b8d1dd0f9ee4f488" - integrity sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg== +baseline-browser-mapping@^2.9.19: + version "2.10.8" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.8.tgz#23d1cea1a85b181c2b8660b6cfe626dc2fb15630" + integrity sha512-PCLz/LXGBsNTErbtB6i5u4eLpHeMfi93aUv5duMmj6caNu6IphS4q6UevDnL36sZQv9lrP11dbPKGMaXPwMKfQ== better-react-mathjax@^2.3.0: version "2.3.0" @@ -3278,26 +3278,26 @@ next-themes@^0.4.0: resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.4.6.tgz#8d7e92d03b8fea6582892a50a928c9b23502e8b6" integrity sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA== -next@^16.1.6: - version "16.1.6" - resolved "https://registry.yarnpkg.com/next/-/next-16.1.6.tgz#24a861371cbe211be7760d9a89ddf2415e3824de" - integrity sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw== +next@^16.1.7: + version "16.1.7" + resolved "https://registry.yarnpkg.com/next/-/next-16.1.7.tgz#fccdda75050ffc11ace27526b8a9ac7c308c8c48" + integrity sha512-WM0L7WrSvKwoLegLYr6V+mz+RIofqQgVAfHhMp9a88ms0cFX8iX9ew+snpWlSBwpkURJOUdvCEt3uLl3NNzvWg== dependencies: - "@next/env" "16.1.6" + "@next/env" "16.1.7" "@swc/helpers" "0.5.15" - baseline-browser-mapping "^2.8.3" + baseline-browser-mapping "^2.9.19" caniuse-lite "^1.0.30001579" postcss "8.4.31" styled-jsx "5.1.6" optionalDependencies: - "@next/swc-darwin-arm64" "16.1.6" - "@next/swc-darwin-x64" "16.1.6" - "@next/swc-linux-arm64-gnu" "16.1.6" - "@next/swc-linux-arm64-musl" "16.1.6" - "@next/swc-linux-x64-gnu" "16.1.6" - "@next/swc-linux-x64-musl" "16.1.6" - "@next/swc-win32-arm64-msvc" "16.1.6" - "@next/swc-win32-x64-msvc" "16.1.6" + "@next/swc-darwin-arm64" "16.1.7" + "@next/swc-darwin-x64" "16.1.7" + "@next/swc-linux-arm64-gnu" "16.1.7" + "@next/swc-linux-arm64-musl" "16.1.7" + "@next/swc-linux-x64-gnu" "16.1.7" + "@next/swc-linux-x64-musl" "16.1.7" + "@next/swc-win32-arm64-msvc" "16.1.7" + "@next/swc-win32-x64-msvc" "16.1.7" sharp "^0.34.4" nextra-theme-docs@^4.6.1: