@liiift-studio/sanity-font-manager 2.3.5 → 2.3.7
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.
- package/README.md +16 -0
- package/dist/index.js +226 -0
- package/dist/index.mjs +225 -0
- package/package.json +8 -2
- package/src/index.js +1 -0
- package/src/schema/stylesField.js +250 -0
package/README.md
CHANGED
|
@@ -266,6 +266,22 @@ import { styleCountField } from '@liiift-studio/sanity-font-manager';
|
|
|
266
266
|
styleCountField,
|
|
267
267
|
```
|
|
268
268
|
|
|
269
|
+
### `stylisticSetField`
|
|
270
|
+
|
|
271
|
+
A complete `stylisticSet` object field for the `stylisticSets` group. Contains two sub-arrays: `featured` (highlighted words/phrases with per-character backtick syntax, stylistic feature picker, size, and CSS overrides) and `sets` (full catalogue of feature → glyph mappings). Both include the full OpenType feature dropdown (44 named features + all 20 stylistic sets).
|
|
272
|
+
|
|
273
|
+
```js
|
|
274
|
+
import { stylisticSetField } from '@liiift-studio/sanity-font-manager';
|
|
275
|
+
|
|
276
|
+
// In your typeface schema fields array:
|
|
277
|
+
stylisticSetField,
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Requires the `stylisticSets` group to be declared in your schema's `groups` array:
|
|
281
|
+
```js
|
|
282
|
+
{ name: 'stylisticSets', title: 'Stylistic Sets' }
|
|
283
|
+
```
|
|
284
|
+
|
|
269
285
|
---
|
|
270
286
|
|
|
271
287
|
## Hook
|
package/dist/index.js
CHANGED
|
@@ -50,6 +50,7 @@ __export(index_exports, {
|
|
|
50
50
|
VariableInstanceReferencesInput: () => VariableInstanceReferencesInput,
|
|
51
51
|
addItalicToFontTitle: () => addItalicToFontTitle,
|
|
52
52
|
createFontObject: () => createFontObject,
|
|
53
|
+
createStylesField: () => createStylesField,
|
|
53
54
|
determineWeight: () => determineWeight,
|
|
54
55
|
expandAbbreviations: () => expandAbbreviations,
|
|
55
56
|
extractFontMetadata: () => extractFontMetadata,
|
|
@@ -6650,6 +6651,230 @@ var stylisticSetField = {
|
|
|
6650
6651
|
}
|
|
6651
6652
|
]
|
|
6652
6653
|
};
|
|
6654
|
+
|
|
6655
|
+
// src/schema/stylesField.js
|
|
6656
|
+
var import_sanity_advanced_reference_array = require("sanity-advanced-reference-array");
|
|
6657
|
+
var fontsFilter = async ({ getClient, document, parent }) => {
|
|
6658
|
+
const client = getClient({ apiVersion: "2022-11-09" });
|
|
6659
|
+
const typefaceName = document.title;
|
|
6660
|
+
const fonts = await client.fetch('*[_type == "font" && lower(typefaceName) == lower($typefaceName)]', { typefaceName });
|
|
6661
|
+
const relatedItemsFiltered = fonts.map((f) => f._id).filter(Boolean);
|
|
6662
|
+
const existingItems = parent.map((f) => f._ref).filter(Boolean);
|
|
6663
|
+
return {
|
|
6664
|
+
filter: "!(_id in $existingItems) && (_id in $relatedItemsFiltered)",
|
|
6665
|
+
params: { existingItems, relatedItemsFiltered }
|
|
6666
|
+
};
|
|
6667
|
+
};
|
|
6668
|
+
var variableFontsFilter = async ({ getClient, document, parent }) => {
|
|
6669
|
+
const client = getClient({ apiVersion: "2022-11-09" });
|
|
6670
|
+
const typefaceName = document.title;
|
|
6671
|
+
const existingItems = parent.map((f) => f._ref).filter(Boolean);
|
|
6672
|
+
const fonts = await client.fetch('*[_type == "font" && typefaceName == $typefaceName && variableFont == true]', { typefaceName });
|
|
6673
|
+
const relatedItemsFiltered = fonts.map((f) => f._id).filter(Boolean);
|
|
6674
|
+
return {
|
|
6675
|
+
filter: "!(_id in $existingItems) && (_id in $relatedItemsFiltered)",
|
|
6676
|
+
params: { existingItems, relatedItemsFiltered }
|
|
6677
|
+
};
|
|
6678
|
+
};
|
|
6679
|
+
function createStylesField({
|
|
6680
|
+
free = false,
|
|
6681
|
+
displayStyles = true,
|
|
6682
|
+
sortHeaviestFirst = false,
|
|
6683
|
+
buySectionColumns = false,
|
|
6684
|
+
fontSizeMultiplier = false,
|
|
6685
|
+
serif = false,
|
|
6686
|
+
regenerateSubfamilies: regenerateSubfamilies2 = false,
|
|
6687
|
+
subfamilyFontSizeMultiplier = false,
|
|
6688
|
+
subfamilyListOrder = false,
|
|
6689
|
+
subfamilyPreferredStyle = false,
|
|
6690
|
+
subfamilyFontFilter = false,
|
|
6691
|
+
subfamilyPreview = false,
|
|
6692
|
+
pairs = true
|
|
6693
|
+
} = {}) {
|
|
6694
|
+
const subfamilyFields = [
|
|
6695
|
+
{
|
|
6696
|
+
title: "Title",
|
|
6697
|
+
name: "title",
|
|
6698
|
+
type: "string"
|
|
6699
|
+
},
|
|
6700
|
+
...subfamilyFontSizeMultiplier ? [{
|
|
6701
|
+
title: "Subfamily Font Size Multiplier",
|
|
6702
|
+
name: "fontSizeMultiplier",
|
|
6703
|
+
type: "number",
|
|
6704
|
+
initialValue: 1,
|
|
6705
|
+
description: "Adjust font size for this subfamily in the Family Overview (Design Space). Default is 1.0 (100%). Range: 0.5 to 2.0",
|
|
6706
|
+
validation: (Rule) => Rule.min(0.5).max(2).precision(2)
|
|
6707
|
+
}] : [],
|
|
6708
|
+
...subfamilyListOrder ? [{
|
|
6709
|
+
title: "Use List Order",
|
|
6710
|
+
name: "useListOrder",
|
|
6711
|
+
type: "boolean",
|
|
6712
|
+
initialValue: false,
|
|
6713
|
+
description: "Display fonts in the manual order listed below, bypassing programmatic weight-based sorting in the Family Overview."
|
|
6714
|
+
}] : [],
|
|
6715
|
+
{
|
|
6716
|
+
title: "Fonts",
|
|
6717
|
+
name: "fonts",
|
|
6718
|
+
type: "array",
|
|
6719
|
+
components: { input: import_sanity_advanced_reference_array.AdvancedRefArray },
|
|
6720
|
+
of: [{ type: "reference", weak: true, to: [{ type: "font" }] }],
|
|
6721
|
+
options: {
|
|
6722
|
+
sortable: true,
|
|
6723
|
+
...subfamilyFontFilter ? { filter: fontsFilter } : {}
|
|
6724
|
+
}
|
|
6725
|
+
},
|
|
6726
|
+
...subfamilyPreferredStyle ? [{
|
|
6727
|
+
title: "SubFamily Preferred Style",
|
|
6728
|
+
name: "preferredStyle",
|
|
6729
|
+
type: "reference",
|
|
6730
|
+
weak: true,
|
|
6731
|
+
to: [{ type: "font" }],
|
|
6732
|
+
options: {
|
|
6733
|
+
filter: async ({ getClient, document, parent }) => {
|
|
6734
|
+
const client = getClient({ apiVersion: "2022-11-09" });
|
|
6735
|
+
const typefaceName = document.title;
|
|
6736
|
+
const fonts = await client.fetch('*[_type == "font" && typefaceName == $typefaceName && variableFont == false]', { typefaceName });
|
|
6737
|
+
const relatedItemsFiltered = fonts.map((f) => f._id).filter(Boolean);
|
|
6738
|
+
const existingItems = parent.fonts.map((f) => f._ref).filter(Boolean);
|
|
6739
|
+
return {
|
|
6740
|
+
filter: "(_id in $existingItems) && (_id in $relatedItemsFiltered)",
|
|
6741
|
+
params: { existingItems, relatedItemsFiltered }
|
|
6742
|
+
};
|
|
6743
|
+
}
|
|
6744
|
+
}
|
|
6745
|
+
}] : []
|
|
6746
|
+
];
|
|
6747
|
+
const subfamilyItem = {
|
|
6748
|
+
type: "object",
|
|
6749
|
+
fields: subfamilyFields,
|
|
6750
|
+
...subfamilyPreview ? {
|
|
6751
|
+
preview: {
|
|
6752
|
+
select: { title: "title", fonts: "fonts" },
|
|
6753
|
+
prepare(props) {
|
|
6754
|
+
const numFonts = Object.keys(props.fonts || {}).length;
|
|
6755
|
+
return { title: props.title, subtitle: `${numFonts} fonts` };
|
|
6756
|
+
}
|
|
6757
|
+
}
|
|
6758
|
+
} : {}
|
|
6759
|
+
};
|
|
6760
|
+
const fields = [
|
|
6761
|
+
...free ? [{
|
|
6762
|
+
title: "Free Typeface",
|
|
6763
|
+
name: "free",
|
|
6764
|
+
type: "boolean",
|
|
6765
|
+
description: 'This typeface is free to download and use. This will alter the "Buy" button and checkout experience.',
|
|
6766
|
+
initialValue: false
|
|
6767
|
+
}] : [],
|
|
6768
|
+
{
|
|
6769
|
+
title: "Display All Styles",
|
|
6770
|
+
name: "displayStyles",
|
|
6771
|
+
type: "boolean",
|
|
6772
|
+
initialValue: true,
|
|
6773
|
+
hidden: !displayStyles,
|
|
6774
|
+
description: "Show all Font Styles below collections in Buy Section"
|
|
6775
|
+
},
|
|
6776
|
+
...sortHeaviestFirst ? [{
|
|
6777
|
+
title: "Sort Fonts Heaviest to Lightest",
|
|
6778
|
+
name: "sortHeaviestFirst",
|
|
6779
|
+
type: "boolean",
|
|
6780
|
+
initialValue: false,
|
|
6781
|
+
description: "Sort fonts by weight from heaviest (900) to lightest (100). Default is lightest to heaviest (industry standard)."
|
|
6782
|
+
}] : [],
|
|
6783
|
+
...buySectionColumns ? [{
|
|
6784
|
+
title: "Multi Column Buy Section",
|
|
6785
|
+
name: "buySectionColumns",
|
|
6786
|
+
type: "boolean",
|
|
6787
|
+
initialValue: true,
|
|
6788
|
+
description: "Choose Single Column or Multi Column for the Buy Section, Default is Multi Column"
|
|
6789
|
+
}] : [],
|
|
6790
|
+
...fontSizeMultiplier ? [{
|
|
6791
|
+
title: "Style Grid Font Size Multiplier",
|
|
6792
|
+
name: "fontSizeMultiplier",
|
|
6793
|
+
type: "number",
|
|
6794
|
+
initialValue: 1,
|
|
6795
|
+
description: "Adjust font size in the buy section style grid. Default is 1.0 (100%). Range: 0.5 to 2.0",
|
|
6796
|
+
validation: (Rule) => Rule.min(0.5).max(2).precision(2)
|
|
6797
|
+
}] : [],
|
|
6798
|
+
...serif ? [{
|
|
6799
|
+
title: "Includes Serifs",
|
|
6800
|
+
name: "serif",
|
|
6801
|
+
type: "boolean",
|
|
6802
|
+
initialValue: false,
|
|
6803
|
+
description: "Check if this typeface includes serif letterforms. Used for typeface overview serif/sans filters. Frontend automatically treats non-serif typefaces as sans serif."
|
|
6804
|
+
}] : [],
|
|
6805
|
+
{
|
|
6806
|
+
title: "Fonts",
|
|
6807
|
+
name: "fonts",
|
|
6808
|
+
type: "array",
|
|
6809
|
+
components: { input: import_sanity_advanced_reference_array.AdvancedRefArray },
|
|
6810
|
+
of: [{
|
|
6811
|
+
type: "reference",
|
|
6812
|
+
weak: true,
|
|
6813
|
+
to: [{ type: "font" }],
|
|
6814
|
+
options: { filter: fontsFilter }
|
|
6815
|
+
}],
|
|
6816
|
+
options: { sortable: true }
|
|
6817
|
+
},
|
|
6818
|
+
{
|
|
6819
|
+
title: "Variable Fonts",
|
|
6820
|
+
name: "variableFont",
|
|
6821
|
+
type: "array",
|
|
6822
|
+
components: { input: import_sanity_advanced_reference_array.AdvancedRefArray },
|
|
6823
|
+
of: [{
|
|
6824
|
+
type: "reference",
|
|
6825
|
+
weak: true,
|
|
6826
|
+
to: [{ type: "font" }],
|
|
6827
|
+
options: { filter: variableFontsFilter }
|
|
6828
|
+
}],
|
|
6829
|
+
description: "Variable fonts are automatically included as a bonus when customers purchase all non-variable styles of this typeface.",
|
|
6830
|
+
options: { sortable: true }
|
|
6831
|
+
},
|
|
6832
|
+
...regenerateSubfamilies2 ? [{
|
|
6833
|
+
title: "Regenerate Subfamilies",
|
|
6834
|
+
name: "regenerateSubfamilies",
|
|
6835
|
+
type: "string",
|
|
6836
|
+
hidden: ({ parent }) => {
|
|
6837
|
+
var _a, _b, _c, _d;
|
|
6838
|
+
return ((_b = (_a = parent == null ? void 0 : parent.styles) == null ? void 0 : _a.subfamilies) == null ? void 0 : _b.length) === 0 || ((_d = (_c = parent == null ? void 0 : parent.styles) == null ? void 0 : _c.fonts) == null ? void 0 : _d.length) === 0;
|
|
6839
|
+
},
|
|
6840
|
+
description: "Regenerates subfamily groups based on the fonts in this typeface.",
|
|
6841
|
+
components: { input: RegenerateSubfamiliesComponent }
|
|
6842
|
+
}] : [],
|
|
6843
|
+
{
|
|
6844
|
+
title: "Sub Families",
|
|
6845
|
+
name: "subfamilies",
|
|
6846
|
+
type: "array",
|
|
6847
|
+
of: [subfamilyItem]
|
|
6848
|
+
},
|
|
6849
|
+
{
|
|
6850
|
+
title: "Collections",
|
|
6851
|
+
name: "collections",
|
|
6852
|
+
type: "array",
|
|
6853
|
+
components: { input: import_sanity_advanced_reference_array.AdvancedRefArray },
|
|
6854
|
+
of: [{ type: "reference", weak: true, to: [{ type: "collection" }] }],
|
|
6855
|
+
options: { sortable: true },
|
|
6856
|
+
validation: (Rule) => Rule.unique()
|
|
6857
|
+
},
|
|
6858
|
+
{
|
|
6859
|
+
title: "Pairs",
|
|
6860
|
+
name: "pairs",
|
|
6861
|
+
type: "array",
|
|
6862
|
+
components: { input: import_sanity_advanced_reference_array.AdvancedRefArray },
|
|
6863
|
+
of: [{ type: "reference", weak: true, to: [{ type: "pair" }] }],
|
|
6864
|
+
options: { sortable: true },
|
|
6865
|
+
validation: (Rule) => Rule.unique(),
|
|
6866
|
+
hidden: !pairs
|
|
6867
|
+
}
|
|
6868
|
+
];
|
|
6869
|
+
return {
|
|
6870
|
+
title: "Styles",
|
|
6871
|
+
name: "styles",
|
|
6872
|
+
type: "object",
|
|
6873
|
+
group: "styles",
|
|
6874
|
+
fields,
|
|
6875
|
+
options: { collapsible: true }
|
|
6876
|
+
};
|
|
6877
|
+
}
|
|
6653
6878
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6654
6879
|
0 && (module.exports = {
|
|
6655
6880
|
BatchUploadFonts,
|
|
@@ -6673,6 +6898,7 @@ var stylisticSetField = {
|
|
|
6673
6898
|
VariableInstanceReferencesInput,
|
|
6674
6899
|
addItalicToFontTitle,
|
|
6675
6900
|
createFontObject,
|
|
6901
|
+
createStylesField,
|
|
6676
6902
|
determineWeight,
|
|
6677
6903
|
expandAbbreviations,
|
|
6678
6904
|
extractFontMetadata,
|
package/dist/index.mjs
CHANGED
|
@@ -6565,6 +6565,230 @@ var stylisticSetField = {
|
|
|
6565
6565
|
}
|
|
6566
6566
|
]
|
|
6567
6567
|
};
|
|
6568
|
+
|
|
6569
|
+
// src/schema/stylesField.js
|
|
6570
|
+
import { AdvancedRefArray } from "sanity-advanced-reference-array";
|
|
6571
|
+
var fontsFilter = async ({ getClient, document, parent }) => {
|
|
6572
|
+
const client = getClient({ apiVersion: "2022-11-09" });
|
|
6573
|
+
const typefaceName = document.title;
|
|
6574
|
+
const fonts = await client.fetch('*[_type == "font" && lower(typefaceName) == lower($typefaceName)]', { typefaceName });
|
|
6575
|
+
const relatedItemsFiltered = fonts.map((f) => f._id).filter(Boolean);
|
|
6576
|
+
const existingItems = parent.map((f) => f._ref).filter(Boolean);
|
|
6577
|
+
return {
|
|
6578
|
+
filter: "!(_id in $existingItems) && (_id in $relatedItemsFiltered)",
|
|
6579
|
+
params: { existingItems, relatedItemsFiltered }
|
|
6580
|
+
};
|
|
6581
|
+
};
|
|
6582
|
+
var variableFontsFilter = async ({ getClient, document, parent }) => {
|
|
6583
|
+
const client = getClient({ apiVersion: "2022-11-09" });
|
|
6584
|
+
const typefaceName = document.title;
|
|
6585
|
+
const existingItems = parent.map((f) => f._ref).filter(Boolean);
|
|
6586
|
+
const fonts = await client.fetch('*[_type == "font" && typefaceName == $typefaceName && variableFont == true]', { typefaceName });
|
|
6587
|
+
const relatedItemsFiltered = fonts.map((f) => f._id).filter(Boolean);
|
|
6588
|
+
return {
|
|
6589
|
+
filter: "!(_id in $existingItems) && (_id in $relatedItemsFiltered)",
|
|
6590
|
+
params: { existingItems, relatedItemsFiltered }
|
|
6591
|
+
};
|
|
6592
|
+
};
|
|
6593
|
+
function createStylesField({
|
|
6594
|
+
free = false,
|
|
6595
|
+
displayStyles = true,
|
|
6596
|
+
sortHeaviestFirst = false,
|
|
6597
|
+
buySectionColumns = false,
|
|
6598
|
+
fontSizeMultiplier = false,
|
|
6599
|
+
serif = false,
|
|
6600
|
+
regenerateSubfamilies: regenerateSubfamilies2 = false,
|
|
6601
|
+
subfamilyFontSizeMultiplier = false,
|
|
6602
|
+
subfamilyListOrder = false,
|
|
6603
|
+
subfamilyPreferredStyle = false,
|
|
6604
|
+
subfamilyFontFilter = false,
|
|
6605
|
+
subfamilyPreview = false,
|
|
6606
|
+
pairs = true
|
|
6607
|
+
} = {}) {
|
|
6608
|
+
const subfamilyFields = [
|
|
6609
|
+
{
|
|
6610
|
+
title: "Title",
|
|
6611
|
+
name: "title",
|
|
6612
|
+
type: "string"
|
|
6613
|
+
},
|
|
6614
|
+
...subfamilyFontSizeMultiplier ? [{
|
|
6615
|
+
title: "Subfamily Font Size Multiplier",
|
|
6616
|
+
name: "fontSizeMultiplier",
|
|
6617
|
+
type: "number",
|
|
6618
|
+
initialValue: 1,
|
|
6619
|
+
description: "Adjust font size for this subfamily in the Family Overview (Design Space). Default is 1.0 (100%). Range: 0.5 to 2.0",
|
|
6620
|
+
validation: (Rule) => Rule.min(0.5).max(2).precision(2)
|
|
6621
|
+
}] : [],
|
|
6622
|
+
...subfamilyListOrder ? [{
|
|
6623
|
+
title: "Use List Order",
|
|
6624
|
+
name: "useListOrder",
|
|
6625
|
+
type: "boolean",
|
|
6626
|
+
initialValue: false,
|
|
6627
|
+
description: "Display fonts in the manual order listed below, bypassing programmatic weight-based sorting in the Family Overview."
|
|
6628
|
+
}] : [],
|
|
6629
|
+
{
|
|
6630
|
+
title: "Fonts",
|
|
6631
|
+
name: "fonts",
|
|
6632
|
+
type: "array",
|
|
6633
|
+
components: { input: AdvancedRefArray },
|
|
6634
|
+
of: [{ type: "reference", weak: true, to: [{ type: "font" }] }],
|
|
6635
|
+
options: {
|
|
6636
|
+
sortable: true,
|
|
6637
|
+
...subfamilyFontFilter ? { filter: fontsFilter } : {}
|
|
6638
|
+
}
|
|
6639
|
+
},
|
|
6640
|
+
...subfamilyPreferredStyle ? [{
|
|
6641
|
+
title: "SubFamily Preferred Style",
|
|
6642
|
+
name: "preferredStyle",
|
|
6643
|
+
type: "reference",
|
|
6644
|
+
weak: true,
|
|
6645
|
+
to: [{ type: "font" }],
|
|
6646
|
+
options: {
|
|
6647
|
+
filter: async ({ getClient, document, parent }) => {
|
|
6648
|
+
const client = getClient({ apiVersion: "2022-11-09" });
|
|
6649
|
+
const typefaceName = document.title;
|
|
6650
|
+
const fonts = await client.fetch('*[_type == "font" && typefaceName == $typefaceName && variableFont == false]', { typefaceName });
|
|
6651
|
+
const relatedItemsFiltered = fonts.map((f) => f._id).filter(Boolean);
|
|
6652
|
+
const existingItems = parent.fonts.map((f) => f._ref).filter(Boolean);
|
|
6653
|
+
return {
|
|
6654
|
+
filter: "(_id in $existingItems) && (_id in $relatedItemsFiltered)",
|
|
6655
|
+
params: { existingItems, relatedItemsFiltered }
|
|
6656
|
+
};
|
|
6657
|
+
}
|
|
6658
|
+
}
|
|
6659
|
+
}] : []
|
|
6660
|
+
];
|
|
6661
|
+
const subfamilyItem = {
|
|
6662
|
+
type: "object",
|
|
6663
|
+
fields: subfamilyFields,
|
|
6664
|
+
...subfamilyPreview ? {
|
|
6665
|
+
preview: {
|
|
6666
|
+
select: { title: "title", fonts: "fonts" },
|
|
6667
|
+
prepare(props) {
|
|
6668
|
+
const numFonts = Object.keys(props.fonts || {}).length;
|
|
6669
|
+
return { title: props.title, subtitle: `${numFonts} fonts` };
|
|
6670
|
+
}
|
|
6671
|
+
}
|
|
6672
|
+
} : {}
|
|
6673
|
+
};
|
|
6674
|
+
const fields = [
|
|
6675
|
+
...free ? [{
|
|
6676
|
+
title: "Free Typeface",
|
|
6677
|
+
name: "free",
|
|
6678
|
+
type: "boolean",
|
|
6679
|
+
description: 'This typeface is free to download and use. This will alter the "Buy" button and checkout experience.',
|
|
6680
|
+
initialValue: false
|
|
6681
|
+
}] : [],
|
|
6682
|
+
{
|
|
6683
|
+
title: "Display All Styles",
|
|
6684
|
+
name: "displayStyles",
|
|
6685
|
+
type: "boolean",
|
|
6686
|
+
initialValue: true,
|
|
6687
|
+
hidden: !displayStyles,
|
|
6688
|
+
description: "Show all Font Styles below collections in Buy Section"
|
|
6689
|
+
},
|
|
6690
|
+
...sortHeaviestFirst ? [{
|
|
6691
|
+
title: "Sort Fonts Heaviest to Lightest",
|
|
6692
|
+
name: "sortHeaviestFirst",
|
|
6693
|
+
type: "boolean",
|
|
6694
|
+
initialValue: false,
|
|
6695
|
+
description: "Sort fonts by weight from heaviest (900) to lightest (100). Default is lightest to heaviest (industry standard)."
|
|
6696
|
+
}] : [],
|
|
6697
|
+
...buySectionColumns ? [{
|
|
6698
|
+
title: "Multi Column Buy Section",
|
|
6699
|
+
name: "buySectionColumns",
|
|
6700
|
+
type: "boolean",
|
|
6701
|
+
initialValue: true,
|
|
6702
|
+
description: "Choose Single Column or Multi Column for the Buy Section, Default is Multi Column"
|
|
6703
|
+
}] : [],
|
|
6704
|
+
...fontSizeMultiplier ? [{
|
|
6705
|
+
title: "Style Grid Font Size Multiplier",
|
|
6706
|
+
name: "fontSizeMultiplier",
|
|
6707
|
+
type: "number",
|
|
6708
|
+
initialValue: 1,
|
|
6709
|
+
description: "Adjust font size in the buy section style grid. Default is 1.0 (100%). Range: 0.5 to 2.0",
|
|
6710
|
+
validation: (Rule) => Rule.min(0.5).max(2).precision(2)
|
|
6711
|
+
}] : [],
|
|
6712
|
+
...serif ? [{
|
|
6713
|
+
title: "Includes Serifs",
|
|
6714
|
+
name: "serif",
|
|
6715
|
+
type: "boolean",
|
|
6716
|
+
initialValue: false,
|
|
6717
|
+
description: "Check if this typeface includes serif letterforms. Used for typeface overview serif/sans filters. Frontend automatically treats non-serif typefaces as sans serif."
|
|
6718
|
+
}] : [],
|
|
6719
|
+
{
|
|
6720
|
+
title: "Fonts",
|
|
6721
|
+
name: "fonts",
|
|
6722
|
+
type: "array",
|
|
6723
|
+
components: { input: AdvancedRefArray },
|
|
6724
|
+
of: [{
|
|
6725
|
+
type: "reference",
|
|
6726
|
+
weak: true,
|
|
6727
|
+
to: [{ type: "font" }],
|
|
6728
|
+
options: { filter: fontsFilter }
|
|
6729
|
+
}],
|
|
6730
|
+
options: { sortable: true }
|
|
6731
|
+
},
|
|
6732
|
+
{
|
|
6733
|
+
title: "Variable Fonts",
|
|
6734
|
+
name: "variableFont",
|
|
6735
|
+
type: "array",
|
|
6736
|
+
components: { input: AdvancedRefArray },
|
|
6737
|
+
of: [{
|
|
6738
|
+
type: "reference",
|
|
6739
|
+
weak: true,
|
|
6740
|
+
to: [{ type: "font" }],
|
|
6741
|
+
options: { filter: variableFontsFilter }
|
|
6742
|
+
}],
|
|
6743
|
+
description: "Variable fonts are automatically included as a bonus when customers purchase all non-variable styles of this typeface.",
|
|
6744
|
+
options: { sortable: true }
|
|
6745
|
+
},
|
|
6746
|
+
...regenerateSubfamilies2 ? [{
|
|
6747
|
+
title: "Regenerate Subfamilies",
|
|
6748
|
+
name: "regenerateSubfamilies",
|
|
6749
|
+
type: "string",
|
|
6750
|
+
hidden: ({ parent }) => {
|
|
6751
|
+
var _a, _b, _c, _d;
|
|
6752
|
+
return ((_b = (_a = parent == null ? void 0 : parent.styles) == null ? void 0 : _a.subfamilies) == null ? void 0 : _b.length) === 0 || ((_d = (_c = parent == null ? void 0 : parent.styles) == null ? void 0 : _c.fonts) == null ? void 0 : _d.length) === 0;
|
|
6753
|
+
},
|
|
6754
|
+
description: "Regenerates subfamily groups based on the fonts in this typeface.",
|
|
6755
|
+
components: { input: RegenerateSubfamiliesComponent }
|
|
6756
|
+
}] : [],
|
|
6757
|
+
{
|
|
6758
|
+
title: "Sub Families",
|
|
6759
|
+
name: "subfamilies",
|
|
6760
|
+
type: "array",
|
|
6761
|
+
of: [subfamilyItem]
|
|
6762
|
+
},
|
|
6763
|
+
{
|
|
6764
|
+
title: "Collections",
|
|
6765
|
+
name: "collections",
|
|
6766
|
+
type: "array",
|
|
6767
|
+
components: { input: AdvancedRefArray },
|
|
6768
|
+
of: [{ type: "reference", weak: true, to: [{ type: "collection" }] }],
|
|
6769
|
+
options: { sortable: true },
|
|
6770
|
+
validation: (Rule) => Rule.unique()
|
|
6771
|
+
},
|
|
6772
|
+
{
|
|
6773
|
+
title: "Pairs",
|
|
6774
|
+
name: "pairs",
|
|
6775
|
+
type: "array",
|
|
6776
|
+
components: { input: AdvancedRefArray },
|
|
6777
|
+
of: [{ type: "reference", weak: true, to: [{ type: "pair" }] }],
|
|
6778
|
+
options: { sortable: true },
|
|
6779
|
+
validation: (Rule) => Rule.unique(),
|
|
6780
|
+
hidden: !pairs
|
|
6781
|
+
}
|
|
6782
|
+
];
|
|
6783
|
+
return {
|
|
6784
|
+
title: "Styles",
|
|
6785
|
+
name: "styles",
|
|
6786
|
+
type: "object",
|
|
6787
|
+
group: "styles",
|
|
6788
|
+
fields,
|
|
6789
|
+
options: { collapsible: true }
|
|
6790
|
+
};
|
|
6791
|
+
}
|
|
6568
6792
|
export {
|
|
6569
6793
|
BatchUploadFonts,
|
|
6570
6794
|
FontScriptUploaderComponent,
|
|
@@ -6587,6 +6811,7 @@ export {
|
|
|
6587
6811
|
VariableInstanceReferencesInput,
|
|
6588
6812
|
addItalicToFontTitle,
|
|
6589
6813
|
createFontObject,
|
|
6814
|
+
createStylesField,
|
|
6590
6815
|
determineWeight,
|
|
6591
6816
|
expandAbbreviations,
|
|
6592
6817
|
extractFontMetadata,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liiift-studio/sanity-font-manager",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.7",
|
|
4
4
|
"description": "Sanity Studio plugin — full font management suite with batch upload, format conversion, metadata extraction, CSS generation, collection/pair generation, and script variant support. Supports Sanity v3, v4, and v5.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Liiift Studio",
|
|
@@ -59,7 +59,13 @@
|
|
|
59
59
|
"@sanity/icons": ">=3",
|
|
60
60
|
"@sanity/ui": ">=3",
|
|
61
61
|
"react": ">=18",
|
|
62
|
-
"sanity": ">=3"
|
|
62
|
+
"sanity": ">=3",
|
|
63
|
+
"sanity-advanced-reference-array": ">=1"
|
|
64
|
+
},
|
|
65
|
+
"peerDependenciesMeta": {
|
|
66
|
+
"sanity-advanced-reference-array": {
|
|
67
|
+
"optional": true
|
|
68
|
+
}
|
|
63
69
|
},
|
|
64
70
|
"devDependencies": {
|
|
65
71
|
"@sanity/icons": "^3",
|
package/src/index.js
CHANGED
|
@@ -57,6 +57,7 @@ export { sanitizeForSanityId } from './utils/sanitizeForSanityId.js';
|
|
|
57
57
|
export { openTypeField } from './schema/openTypeField.js';
|
|
58
58
|
export { styleCountField } from './schema/styleCountField.js';
|
|
59
59
|
export { stylisticSetField } from './schema/stylisticSetField.js';
|
|
60
|
+
export { createStylesField } from './schema/stylesField.js';
|
|
60
61
|
|
|
61
62
|
// Keyword utilities
|
|
62
63
|
export {
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
// Sanity schema factory function for the Styles object field — call createStylesField(options) to generate the field definition for a typeface document
|
|
2
|
+
import { AdvancedRefArray } from 'sanity-advanced-reference-array';
|
|
3
|
+
import { RegenerateSubfamiliesComponent } from '../components/RegenerateSubfamiliesComponent.jsx';
|
|
4
|
+
|
|
5
|
+
// Shared GROQ filter — returns fonts from the same typeface, excluding items already in the array
|
|
6
|
+
const fontsFilter = async ({ getClient, document, parent }) => {
|
|
7
|
+
const client = getClient({ apiVersion: '2022-11-09' });
|
|
8
|
+
const typefaceName = document.title;
|
|
9
|
+
const fonts = await client.fetch('*[_type == "font" && lower(typefaceName) == lower($typefaceName)]', { typefaceName });
|
|
10
|
+
const relatedItemsFiltered = fonts.map(f => f._id).filter(Boolean);
|
|
11
|
+
const existingItems = parent.map(f => f._ref).filter(Boolean);
|
|
12
|
+
return {
|
|
13
|
+
filter: '!(_id in $existingItems) && (_id in $relatedItemsFiltered)',
|
|
14
|
+
params: { existingItems, relatedItemsFiltered },
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Shared GROQ filter — returns variable fonts from the same typeface, excluding items already in the array
|
|
19
|
+
const variableFontsFilter = async ({ getClient, document, parent }) => {
|
|
20
|
+
const client = getClient({ apiVersion: '2022-11-09' });
|
|
21
|
+
const typefaceName = document.title;
|
|
22
|
+
const existingItems = parent.map(f => f._ref).filter(Boolean);
|
|
23
|
+
const fonts = await client.fetch('*[_type == "font" && typefaceName == $typefaceName && variableFont == true]', { typefaceName });
|
|
24
|
+
const relatedItemsFiltered = fonts.map(f => f._id).filter(Boolean);
|
|
25
|
+
return {
|
|
26
|
+
filter: '!(_id in $existingItems) && (_id in $relatedItemsFiltered)',
|
|
27
|
+
params: { existingItems, relatedItemsFiltered },
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Generates the Styles object field for a typeface document with configurable per-site options.
|
|
33
|
+
* @param {Object} options
|
|
34
|
+
* @param {boolean} [options.free=false] - Add a "Free Typeface" boolean field
|
|
35
|
+
* @param {boolean} [options.displayStyles=true] - Show the "Display All Styles" toggle to editors (false = hidden)
|
|
36
|
+
* @param {boolean} [options.sortHeaviestFirst=false] - Add sort order toggle (heaviest to lightest)
|
|
37
|
+
* @param {boolean} [options.buySectionColumns=false] - Add multi-column buy section toggle
|
|
38
|
+
* @param {boolean} [options.fontSizeMultiplier=false] - Add style grid font size multiplier
|
|
39
|
+
* @param {boolean} [options.serif=false] - Add serif/sans classification flag
|
|
40
|
+
* @param {boolean} [options.regenerateSubfamilies=false] - Add the RegenerateSubfamilies action field
|
|
41
|
+
* @param {boolean} [options.subfamilyFontSizeMultiplier=false] - Add per-subfamily font size multiplier
|
|
42
|
+
* @param {boolean} [options.subfamilyListOrder=false] - Add per-subfamily manual order toggle
|
|
43
|
+
* @param {boolean} [options.subfamilyPreferredStyle=false] - Add per-subfamily preferred style reference
|
|
44
|
+
* @param {boolean} [options.subfamilyFontFilter=false] - Filter subfamily font picker to typeface fonts only
|
|
45
|
+
* @param {boolean} [options.subfamilyPreview=false] - Add preview to subfamily array items showing font count
|
|
46
|
+
* @param {boolean} [options.pairs=true] - Show the pairs array to editors (false = hidden)
|
|
47
|
+
*/
|
|
48
|
+
export function createStylesField({
|
|
49
|
+
free = false,
|
|
50
|
+
displayStyles = true,
|
|
51
|
+
sortHeaviestFirst = false,
|
|
52
|
+
buySectionColumns = false,
|
|
53
|
+
fontSizeMultiplier = false,
|
|
54
|
+
serif = false,
|
|
55
|
+
regenerateSubfamilies = false,
|
|
56
|
+
subfamilyFontSizeMultiplier = false,
|
|
57
|
+
subfamilyListOrder = false,
|
|
58
|
+
subfamilyPreferredStyle = false,
|
|
59
|
+
subfamilyFontFilter = false,
|
|
60
|
+
subfamilyPreview = false,
|
|
61
|
+
pairs = true,
|
|
62
|
+
} = {}) {
|
|
63
|
+
|
|
64
|
+
// Build the subfamily object item fields conditionally
|
|
65
|
+
const subfamilyFields = [
|
|
66
|
+
{
|
|
67
|
+
title: 'Title',
|
|
68
|
+
name: 'title',
|
|
69
|
+
type: 'string',
|
|
70
|
+
},
|
|
71
|
+
...(subfamilyFontSizeMultiplier ? [{
|
|
72
|
+
title: 'Subfamily Font Size Multiplier',
|
|
73
|
+
name: 'fontSizeMultiplier',
|
|
74
|
+
type: 'number',
|
|
75
|
+
initialValue: 1.0,
|
|
76
|
+
description: 'Adjust font size for this subfamily in the Family Overview (Design Space). Default is 1.0 (100%). Range: 0.5 to 2.0',
|
|
77
|
+
validation: Rule => Rule.min(0.5).max(2.0).precision(2),
|
|
78
|
+
}] : []),
|
|
79
|
+
...(subfamilyListOrder ? [{
|
|
80
|
+
title: 'Use List Order',
|
|
81
|
+
name: 'useListOrder',
|
|
82
|
+
type: 'boolean',
|
|
83
|
+
initialValue: false,
|
|
84
|
+
description: 'Display fonts in the manual order listed below, bypassing programmatic weight-based sorting in the Family Overview.',
|
|
85
|
+
}] : []),
|
|
86
|
+
{
|
|
87
|
+
title: 'Fonts',
|
|
88
|
+
name: 'fonts',
|
|
89
|
+
type: 'array',
|
|
90
|
+
components: { input: AdvancedRefArray },
|
|
91
|
+
of: [{ type: 'reference', weak: true, to: [{ type: 'font' }] }],
|
|
92
|
+
options: {
|
|
93
|
+
sortable: true,
|
|
94
|
+
...(subfamilyFontFilter ? { filter: fontsFilter } : {}),
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
...(subfamilyPreferredStyle ? [{
|
|
98
|
+
title: 'SubFamily Preferred Style',
|
|
99
|
+
name: 'preferredStyle',
|
|
100
|
+
type: 'reference',
|
|
101
|
+
weak: true,
|
|
102
|
+
to: [{ type: 'font' }],
|
|
103
|
+
options: {
|
|
104
|
+
filter: async ({ getClient, document, parent }) => {
|
|
105
|
+
const client = getClient({ apiVersion: '2022-11-09' });
|
|
106
|
+
const typefaceName = document.title;
|
|
107
|
+
const fonts = await client.fetch('*[_type == "font" && typefaceName == $typefaceName && variableFont == false]', { typefaceName });
|
|
108
|
+
const relatedItemsFiltered = fonts.map(f => f._id).filter(Boolean);
|
|
109
|
+
const existingItems = parent.fonts.map(f => f._ref).filter(Boolean);
|
|
110
|
+
return {
|
|
111
|
+
filter: '(_id in $existingItems) && (_id in $relatedItemsFiltered)',
|
|
112
|
+
params: { existingItems, relatedItemsFiltered },
|
|
113
|
+
};
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
}] : []),
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
const subfamilyItem = {
|
|
120
|
+
type: 'object',
|
|
121
|
+
fields: subfamilyFields,
|
|
122
|
+
...(subfamilyPreview ? {
|
|
123
|
+
preview: {
|
|
124
|
+
select: { title: 'title', fonts: 'fonts' },
|
|
125
|
+
prepare(props) {
|
|
126
|
+
const numFonts = Object.keys(props.fonts || {}).length;
|
|
127
|
+
return { title: props.title, subtitle: `${numFonts} fonts` };
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
} : {}),
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const fields = [
|
|
134
|
+
...(free ? [{
|
|
135
|
+
title: 'Free Typeface',
|
|
136
|
+
name: 'free',
|
|
137
|
+
type: 'boolean',
|
|
138
|
+
description: 'This typeface is free to download and use. This will alter the "Buy" button and checkout experience.',
|
|
139
|
+
initialValue: false,
|
|
140
|
+
}] : []),
|
|
141
|
+
{
|
|
142
|
+
title: 'Display All Styles',
|
|
143
|
+
name: 'displayStyles',
|
|
144
|
+
type: 'boolean',
|
|
145
|
+
initialValue: true,
|
|
146
|
+
hidden: !displayStyles,
|
|
147
|
+
description: 'Show all Font Styles below collections in Buy Section',
|
|
148
|
+
},
|
|
149
|
+
...(sortHeaviestFirst ? [{
|
|
150
|
+
title: 'Sort Fonts Heaviest to Lightest',
|
|
151
|
+
name: 'sortHeaviestFirst',
|
|
152
|
+
type: 'boolean',
|
|
153
|
+
initialValue: false,
|
|
154
|
+
description: 'Sort fonts by weight from heaviest (900) to lightest (100). Default is lightest to heaviest (industry standard).',
|
|
155
|
+
}] : []),
|
|
156
|
+
...(buySectionColumns ? [{
|
|
157
|
+
title: 'Multi Column Buy Section',
|
|
158
|
+
name: 'buySectionColumns',
|
|
159
|
+
type: 'boolean',
|
|
160
|
+
initialValue: true,
|
|
161
|
+
description: 'Choose Single Column or Multi Column for the Buy Section, Default is Multi Column',
|
|
162
|
+
}] : []),
|
|
163
|
+
...(fontSizeMultiplier ? [{
|
|
164
|
+
title: 'Style Grid Font Size Multiplier',
|
|
165
|
+
name: 'fontSizeMultiplier',
|
|
166
|
+
type: 'number',
|
|
167
|
+
initialValue: 1.0,
|
|
168
|
+
description: 'Adjust font size in the buy section style grid. Default is 1.0 (100%). Range: 0.5 to 2.0',
|
|
169
|
+
validation: Rule => Rule.min(0.5).max(2.0).precision(2),
|
|
170
|
+
}] : []),
|
|
171
|
+
...(serif ? [{
|
|
172
|
+
title: 'Includes Serifs',
|
|
173
|
+
name: 'serif',
|
|
174
|
+
type: 'boolean',
|
|
175
|
+
initialValue: false,
|
|
176
|
+
description: 'Check if this typeface includes serif letterforms. Used for typeface overview serif/sans filters. Frontend automatically treats non-serif typefaces as sans serif.',
|
|
177
|
+
}] : []),
|
|
178
|
+
{
|
|
179
|
+
title: 'Fonts',
|
|
180
|
+
name: 'fonts',
|
|
181
|
+
type: 'array',
|
|
182
|
+
components: { input: AdvancedRefArray },
|
|
183
|
+
of: [{
|
|
184
|
+
type: 'reference',
|
|
185
|
+
weak: true,
|
|
186
|
+
to: [{ type: 'font' }],
|
|
187
|
+
options: { filter: fontsFilter },
|
|
188
|
+
}],
|
|
189
|
+
options: { sortable: true },
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
title: 'Variable Fonts',
|
|
193
|
+
name: 'variableFont',
|
|
194
|
+
type: 'array',
|
|
195
|
+
components: { input: AdvancedRefArray },
|
|
196
|
+
of: [{
|
|
197
|
+
type: 'reference',
|
|
198
|
+
weak: true,
|
|
199
|
+
to: [{ type: 'font' }],
|
|
200
|
+
options: { filter: variableFontsFilter },
|
|
201
|
+
}],
|
|
202
|
+
description: 'Variable fonts are automatically included as a bonus when customers purchase all non-variable styles of this typeface.',
|
|
203
|
+
options: { sortable: true },
|
|
204
|
+
},
|
|
205
|
+
...(regenerateSubfamilies ? [{
|
|
206
|
+
title: 'Regenerate Subfamilies',
|
|
207
|
+
name: 'regenerateSubfamilies',
|
|
208
|
+
type: 'string',
|
|
209
|
+
hidden: ({ parent }) => {
|
|
210
|
+
return parent?.styles?.subfamilies?.length === 0 || parent?.styles?.fonts?.length === 0;
|
|
211
|
+
},
|
|
212
|
+
description: 'Regenerates subfamily groups based on the fonts in this typeface.',
|
|
213
|
+
components: { input: RegenerateSubfamiliesComponent },
|
|
214
|
+
}] : []),
|
|
215
|
+
{
|
|
216
|
+
title: 'Sub Families',
|
|
217
|
+
name: 'subfamilies',
|
|
218
|
+
type: 'array',
|
|
219
|
+
of: [subfamilyItem],
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
title: 'Collections',
|
|
223
|
+
name: 'collections',
|
|
224
|
+
type: 'array',
|
|
225
|
+
components: { input: AdvancedRefArray },
|
|
226
|
+
of: [{ type: 'reference', weak: true, to: [{ type: 'collection' }] }],
|
|
227
|
+
options: { sortable: true },
|
|
228
|
+
validation: Rule => Rule.unique(),
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
title: 'Pairs',
|
|
232
|
+
name: 'pairs',
|
|
233
|
+
type: 'array',
|
|
234
|
+
components: { input: AdvancedRefArray },
|
|
235
|
+
of: [{ type: 'reference', weak: true, to: [{ type: 'pair' }] }],
|
|
236
|
+
options: { sortable: true },
|
|
237
|
+
validation: Rule => Rule.unique(),
|
|
238
|
+
hidden: !pairs,
|
|
239
|
+
},
|
|
240
|
+
];
|
|
241
|
+
|
|
242
|
+
return {
|
|
243
|
+
title: 'Styles',
|
|
244
|
+
name: 'styles',
|
|
245
|
+
type: 'object',
|
|
246
|
+
group: 'styles',
|
|
247
|
+
fields,
|
|
248
|
+
options: { collapsible: true },
|
|
249
|
+
};
|
|
250
|
+
}
|