@servicetitan/docs-anvil-uikit-contrib 39.2.0 → 39.3.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.
@@ -127,7 +127,7 @@ These are additions to TanStack's standard options:
127
127
  | `autoInitialize` | `true` | Set `initialized` to `true` after first successful fetch. Set to `false` to control it manually |
128
128
  | `onSuccess` | `undefined` | Callback with query data after success. Also fires on `updateQueryData()` |
129
129
  | `onError` | `undefined` | Callback with error object after failure (after retries) |
130
- | `globalClient` | `undefined` | Use a shared page or app-level query client. See [Shared Clients](./04-shared-clients) |
130
+ | `globalClient` | `undefined` | Use a shared page or app-level query client. See [Shared Clients](./shared-clients) |
131
131
 
132
132
  ## Query State
133
133
 
@@ -91,7 +91,7 @@ See all options at [TanStack Query useMutation reference](https://tanstack.com/q
91
91
  | Option | Description |
92
92
  |--------|-------------|
93
93
  | `invalidatedQueries` | Query keys to refetch after successful mutation |
94
- | `globalClient` | Use a shared page or app-level client (see [Shared Clients](./04-shared-clients)) |
94
+ | `globalClient` | Use a shared page or app-level client (see [Shared Clients](./shared-clients)) |
95
95
 
96
96
  ## Mutation State
97
97
 
@@ -36,7 +36,7 @@ export const App: FC = provide({
36
36
  })(observer(() => <YourApp />));
37
37
  ```
38
38
 
39
- Custom config is only supported for local (component-scoped) clients. Shared clients (`'page'`, `'app'`) use consistent defaults across all MFEs — see [Shared Clients](./04-shared-clients).
39
+ Custom config is only supported for local (component-scoped) clients. Shared clients (`'page'`, `'app'`) use consistent defaults across all MFEs — see [Shared Clients](./shared-clients).
40
40
 
41
41
  ## Defaults
42
42
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/docs-anvil-uikit-contrib",
3
- "version": "39.2.0",
3
+ "version": "39.3.1",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,7 +8,8 @@
8
8
  "directory": "docusaurus"
9
9
  },
10
10
  "files": [
11
- "docs"
11
+ "docs",
12
+ "remark"
12
13
  ],
13
14
  "publishConfig": {
14
15
  "access": "public"
@@ -16,5 +17,5 @@
16
17
  "cli": {
17
18
  "webpack": false
18
19
  },
19
- "gitHead": "6bbf9e0d01ace99f5b5d0200025300a0d5c82e94"
20
+ "gitHead": "2e184ec2178bf6b013379398bbd055bb88533055"
20
21
  }
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Remark plugin that inlines demo source code at MDX compile time.
3
+ *
4
+ * For each <CodeDemo srcPath="<pkg>/<path>" /> (or <DemoCodeBlock>) in MDX,
5
+ * this plugin reads the file from disk and adds the contents as a `src` prop
6
+ * on the element. The CodeDemo component then renders that string in the
7
+ * "Source" tab without doing any runtime lookups.
8
+ *
9
+ * Why this exists: the previous approach was a runtime
10
+ * `require(`!!raw-loader!@servicetitan/${srcPath}`)` inside CodeDemo.
11
+ * Webpack expanded that template-literal require into a context module
12
+ * spanning every file under @servicetitan/*, which (a) ballooned the bundle
13
+ * by transitively pulling in vitest/node: imports and (b) crashed HMR in
14
+ * webpack's FileSystemInfo._resolveContextTimestamp on every edit.
15
+ * Resolving srcPath here at MDX compile time eliminates the context module
16
+ * entirely.
17
+ *
18
+ * Why this works under pnpm/yarn/npm: it uses Module.createRequire from the
19
+ * consumer's docusaurus directory, so resolution follows the consumer's
20
+ * actual node_modules layout instead of assuming scoped packages are
21
+ * hoisted as siblings.
22
+ *
23
+ * Usage (in the consumer's docusaurus.config.js, Docusaurus v3+):
24
+ *
25
+ * beforeDefaultRemarkPlugins: [
26
+ * require('@servicetitan/docs-anvil-uikit-contrib/remark/inline-demo-src')({
27
+ * resolveFrom: __dirname,
28
+ * }),
29
+ * ]
30
+ *
31
+ * In Docusaurus v2 the plugin is a no-op: MDX 1's AST doesn't have the
32
+ * mdxJsxFlowElement/mdxJsxTextElement node types we look for, so the walk
33
+ * finds nothing and the consumer's existing CodeDemo runtime keeps working.
34
+ */
35
+
36
+ const fs = require('fs');
37
+ const path = require('path');
38
+ const Module = require('module');
39
+
40
+ const TARGET_NAMES = new Set(['CodeDemo', 'DemoCodeBlock']);
41
+
42
+ /**
43
+ * Builds a package-root resolver scoped to the host project's node_modules.
44
+ *
45
+ * `Module.createRequire` is given a fake file path inside `resolveFrom` so the
46
+ * resulting `require.resolve` walks node_modules starting from there. Without
47
+ * this, resolution would happen relative to this file's location
48
+ * (`packages/docs/remark/`), which lacks the demo packages.
49
+ */
50
+ function makeFindPackageRoot(resolveFrom) {
51
+ const hostRequire = Module.createRequire(path.join(resolveFrom, 'noop.js'));
52
+ return name => {
53
+ try {
54
+ /* Preferred path: resolve `<pkg>/package.json` directly. */
55
+ return path.dirname(hostRequire.resolve(`${name}/package.json`));
56
+ } catch (err) {
57
+ /*
58
+ * Some packages have an `exports` field that omits `./package.json`,
59
+ * which makes the direct resolve throw ERR_PACKAGE_PATH_NOT_EXPORTED.
60
+ * Fall back to resolving the package's main entry, then walking up
61
+ * to the directory that actually contains package.json.
62
+ */
63
+ if (err.code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED') {
64
+ throw err;
65
+ }
66
+ let dir = path.dirname(hostRequire.resolve(name));
67
+ while (!fs.existsSync(path.join(dir, 'package.json'))) {
68
+ const parent = path.dirname(dir);
69
+ if (parent === dir) {
70
+ throw err;
71
+ }
72
+ dir = parent;
73
+ }
74
+ return dir;
75
+ }
76
+ };
77
+ }
78
+
79
+ /*
80
+ * Minimal in-tree visitor; avoids depending on `unist-util-visit` which is
81
+ * ESM-only and would force this CJS plugin to become async.
82
+ */
83
+ function walk(node, fn) {
84
+ if (!node) {
85
+ return;
86
+ }
87
+ fn(node);
88
+ if (Array.isArray(node.children)) {
89
+ for (const child of node.children) {
90
+ walk(child, fn);
91
+ }
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Reads an MDX JSX attribute's string value.
97
+ *
98
+ * For literal attributes (`srcPath="foo/bar"`) MDX 3 stores the string
99
+ * directly on `attr.value`. For expression attributes (`srcPath={...}`) it
100
+ * stores an object whose `.value` is the expression source — we don't try
101
+ * to evaluate that, we only handle plain string literals.
102
+ */
103
+ function getAttrValue(attr) {
104
+ if (typeof attr.value === 'string') {
105
+ return attr.value;
106
+ }
107
+ if (attr.value && typeof attr.value === 'object' && 'value' in attr.value) {
108
+ return attr.value.value;
109
+ }
110
+ return undefined;
111
+ }
112
+
113
+ /**
114
+ * Plugin factory. Called once at config-load time with `{ resolveFrom }`,
115
+ * returns the actual remark plugin (a function returning a tree visitor).
116
+ *
117
+ * We use a factory instead of a bare plugin so each consumer can pass its
118
+ * own `__dirname` for module resolution.
119
+ */
120
+ module.exports = function inlineDemoSrc(options = {}) {
121
+ const resolveFrom = options.resolveFrom || process.cwd();
122
+ const findPackageRoot = makeFindPackageRoot(resolveFrom);
123
+
124
+ return () => tree => {
125
+ walk(tree, node => {
126
+ /*
127
+ * Only MDX 3 JSX element nodes are interesting; v2's MDX 1 uses a
128
+ * different shape, so this plugin is a safe no-op there.
129
+ */
130
+ if (node.type !== 'mdxJsxFlowElement' && node.type !== 'mdxJsxTextElement') {
131
+ return;
132
+ }
133
+ if (!TARGET_NAMES.has(node.name)) {
134
+ return;
135
+ }
136
+ if (!Array.isArray(node.attributes)) {
137
+ return;
138
+ }
139
+ /* If the author already provided a `src` prop manually, leave it. */
140
+ if (node.attributes.some(a => a.name === 'src')) {
141
+ return;
142
+ }
143
+
144
+ const srcPathAttr = node.attributes.find(a => a.name === 'srcPath');
145
+ if (!srcPathAttr) {
146
+ return;
147
+ }
148
+ const srcPath = getAttrValue(srcPathAttr);
149
+ if (typeof srcPath !== 'string') {
150
+ return;
151
+ }
152
+
153
+ /*
154
+ * srcPath is "<package>/<file>" — split on the first slash so
155
+ * multi-segment subpaths like "table/src/demo/overview/table.tsx"
156
+ * are kept intact.
157
+ */
158
+ const slash = srcPath.indexOf('/');
159
+ if (slash < 0) {
160
+ return;
161
+ }
162
+ const pkg = srcPath.slice(0, slash);
163
+ const subpath = srcPath.slice(slash + 1);
164
+
165
+ const fullPath = path.join(findPackageRoot(`@servicetitan/${pkg}`), subpath);
166
+ const src = fs.readFileSync(fullPath, 'utf8');
167
+
168
+ /*
169
+ * Append a synthesized literal `src` attribute. MDX 3's compiler
170
+ * turns this into `src="..."` on the rendered element.
171
+ */
172
+ node.attributes.push({
173
+ type: 'mdxJsxAttribute',
174
+ name: 'src',
175
+ value: src,
176
+ });
177
+ });
178
+ };
179
+ };