@@ -328,6 +328,9 @@ function getThemeApi() {
328328function getPaletteApi ( ) {
329329 return ( typeof window !== 'undefined' && window . MathVisualsPalette ) || null ;
330330}
331+ function getPaletteConfig ( ) {
332+ return ( typeof window !== 'undefined' && window . MathVisualsPaletteConfig ) || null ;
333+ }
331334
332335function getThemeColor ( token , fallback ) {
333336 const theme = getThemeApi ( ) ;
@@ -490,6 +493,53 @@ function sanitizePaletteList(values) {
490493 return sanitized ;
491494}
492495
496+ let graftegnerFillSlotPositions = null ;
497+ function resolveGraftegnerFillSlotPositions ( ) {
498+ if ( Array . isArray ( graftegnerFillSlotPositions ) ) {
499+ return graftegnerFillSlotPositions . slice ( ) ;
500+ }
501+ const config = getPaletteConfig ( ) ;
502+ if ( config && Array . isArray ( config . COLOR_SLOT_GROUPS ) ) {
503+ const group = config . COLOR_SLOT_GROUPS . find ( entry => {
504+ const id = entry && typeof entry . groupId === 'string' ? entry . groupId . trim ( ) . toLowerCase ( ) : '' ;
505+ return id === GRAFTEGNER_GROUP_ID ;
506+ } ) ;
507+ if ( group && Array . isArray ( group . slots ) ) {
508+ const positions = group . slots
509+ . map ( ( slot , index ) => {
510+ const label = slot && typeof slot . label === 'string' ? slot . label . trim ( ) . toLowerCase ( ) : '' ;
511+ return label . includes ( 'fyll' ) ? index : null ;
512+ } )
513+ . filter ( value => Number . isFinite ( value ) ) ;
514+ if ( positions . length ) {
515+ graftegnerFillSlotPositions = positions ;
516+ return positions . slice ( ) ;
517+ }
518+ }
519+ }
520+ graftegnerFillSlotPositions = [ ] ;
521+ return [ ] ;
522+ }
523+
524+ function selectGraftegnerFillColors ( palette ) {
525+ const sanitized = sanitizePaletteList ( palette ) ;
526+ if ( ! sanitized . length ) return [ ] ;
527+ const positions = resolveGraftegnerFillSlotPositions ( ) ;
528+ let fillColors = [ ] ;
529+ if ( positions . length ) {
530+ positions . forEach ( position => {
531+ const color = sanitized [ position ] ;
532+ if ( color ) {
533+ fillColors . push ( color ) ;
534+ }
535+ } ) ;
536+ }
537+ if ( ! fillColors . length ) {
538+ fillColors = sanitized . filter ( ( _ , index ) => index % 2 === 0 ) ;
539+ }
540+ return fillColors ;
541+ }
542+
493543function tryResolveGroupPalette ( resolver ) {
494544 try {
495545 const result = resolver ( ) ;
@@ -7908,12 +7958,19 @@ function setupSettingsForm() {
79087958 const parsed = Number . parseInt ( row . dataset . index , 10 ) ;
79097959 return Number . isFinite ( parsed ) && parsed > 0 ? parsed : 1 ;
79107960 } ;
7911- const computeDefaultColorForIndex = index => normalizeColorValue ( colorFor ( index - 1 ) ) || DEFAULT_COLOR_FALLBACK ;
7961+ const computeDefaultColorForIndex = index => {
7962+ const options = getFunctionColorOptions ( ) ;
7963+ if ( ! options . length ) {
7964+ return normalizeColorValue ( colorFor ( index - 1 ) ) || DEFAULT_COLOR_FALLBACK ;
7965+ }
7966+ const offset = Number . isFinite ( index ) && index > 0 ? Math . trunc ( index - 1 ) : 0 ;
7967+ return normalizeColorValue ( options [ offset % options . length ] ) || DEFAULT_COLOR_FALLBACK ;
7968+ } ;
79127969 let functionColorOptions = [ ] ;
79137970 const resolveFunctionColorOptions = ( ) => {
7914- const palette = resolveCurvePalette ( FUNCTION_COLOR_OPTION_COUNT ) ;
7915- const sanitized = sanitizePaletteList ( palette ) ;
7916- const filled = ensureColorCount ( sanitized , DEFAULT_FUNCTION_COLORS . fallback , FUNCTION_COLOR_OPTION_COUNT ) ;
7971+ const palette = resolveCurvePalette ( FUNCTION_COLOR_OPTION_COUNT * 2 ) ;
7972+ const fillPalette = selectGraftegnerFillColors ( palette ) ;
7973+ const filled = ensureColorCount ( fillPalette , DEFAULT_FUNCTION_COLORS . fallback , FUNCTION_COLOR_OPTION_COUNT ) ;
79177974 return filled . slice ( 0 , FUNCTION_COLOR_OPTION_COUNT ) ;
79187975 } ;
79197976 const getFunctionColorOptions = ( ) => {
@@ -9689,9 +9746,9 @@ function setupSettingsForm() {
96899746 const defaultColor = computeDefaultColorForIndex ( index ) ;
96909747 const manualColor = normalizeFunctionColorChoice ( colorVal ) ;
96919748 const isManualColor = ! ! colorManual && ! ! manualColor ;
9692- const palette = resolveCurvePalette ( 6 ) ;
9749+ const palette = getFunctionColorOptions ( ) ;
96939750 const activeColor = normalizeColorValue ( colorVal )
9694- || normalizeColorValue ( palette [ ( index - 1 ) % 6 ] )
9751+ || normalizeColorValue ( palette [ ( index - 1 ) % palette . length ] )
96959752 || DEFAULT_COLOR_FALLBACK ;
96969753 let colorControlMarkup = `
96979754 <div class="func-color-compact" data-color-picker>
@@ -9704,7 +9761,7 @@ function setupSettingsForm() {
97049761 <div class="color-options" hidden>
97059762 ` ;
97069763
9707- palette . slice ( 0 , 6 ) . forEach ( ( color , idx ) => {
9764+ palette . slice ( 0 , FUNCTION_COLOR_OPTION_COUNT ) . forEach ( ( color , idx ) => {
97089765 const isSelected = normalizeColorValue ( color ) === activeColor ;
97099766 colorControlMarkup += `
97109767 <button type="button" class="color-option-btn ${ isSelected ? 'is-selected' : '' } "
0 commit comments