phlex-reactive 0.16.2 → 0.16.3

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.
@@ -741,7 +741,18 @@ module Phlex
741
741
  # exactly one of field/input: per call — the field form stays the
742
742
  # blessed default:
743
743
  # reactive_filter(input: "#user_tags_query")
744
- def reactive_filter(field = nil, input: nil, option: nil, group: nil, empty: nil)
744
+ #
745
+ # Issue #425: `match:` picks where the query must sit in the haystack —
746
+ # :substring (anywhere, the default), :prefix (at its start) or
747
+ # :word_start (at its start, or right after whitespace or one of
748
+ # - ' ( ) , . /). A long alphabetical list (countries, cities, people)
749
+ # wants :word_start, so "n" keeps Nantes and New York, not every name
750
+ # with an n in it. `fold: true` folds diacritics on BOTH sides before
751
+ # comparing, so "zur" finds Zürich and "zür" still does. The defaults
752
+ # emit nothing, so an existing filter's wire is byte-identical:
753
+ # reactive_filter(:q, match: :word_start, fold: true)
754
+ def reactive_filter(field = nil, input: nil, option: nil, group: nil, empty: nil,
755
+ match: :substring, fold: false)
745
756
  # nil-presence, NOT truthiness: `input: cond && "#sel"` with cond false
746
757
  # must fail loudly in filter_selector! below (a boolean is never a
747
758
  # selector), never slip into the field branch and emit a dead binding.
@@ -768,6 +779,10 @@ module Phlex
768
779
  # byte-stable wire and always-emit an attribute the client would then query).
769
780
  data[:reactive_filter_group] = filter_selector!(:group, group) if group
770
781
  data[:reactive_filter_empty] = filter_selector!(:empty, empty) if empty
782
+ # match:/fold: too (issue #425): the defaults emit nothing.
783
+ mode = filter_match!(match)
784
+ data[:reactive_filter_match] = mode.to_s unless mode == :substring
785
+ data[:reactive_filter_fold] = "true" if fold
771
786
 
772
787
  { data: }
773
788
  end
@@ -1427,8 +1442,24 @@ module Phlex
1427
1442
  LEGACY_SHOW_PREDICATE_KEYS = %i[equals not in gte gt lte lt].freeze
1428
1443
  LEGACY_SHOW_CONNECTIVE_KEYS = %i[all any].freeze
1429
1444
 
1445
+ # reactive_filter's match: modes (issue #425), in the order the error names them.
1446
+ FILTER_MATCH_MODES = %i[substring prefix word_start].freeze
1447
+ private_constant :FILTER_MATCH_MODES
1448
+
1430
1449
  private
1431
1450
 
1451
+ # reactive_filter's match: (issue #425), a Symbol or a String naming one
1452
+ # of FILTER_MATCH_MODES (the reactive_persist storage: precedent).
1453
+ # Anything else raises at render: the client would fall back to
1454
+ # substring matching and the list would narrow the wrong way.
1455
+ def filter_match!(match)
1456
+ mode = match.to_sym if match.is_a?(Symbol) || match.is_a?(String)
1457
+ return mode if FILTER_MATCH_MODES.include?(mode)
1458
+
1459
+ raise ArgumentError,
1460
+ "reactive_filter match: must be one of #{FILTER_MATCH_MODES.join(", ")}, got #{match.inspect}"
1461
+ end
1462
+
1432
1463
  # A reactive_filter/reactive_listnav selector, validated non-blank and
1433
1464
  # stringified (issue #163). A blank selector is a dead binding — the
1434
1465
  # client would silently match nothing — so it fails loudly at render,
@@ -10,7 +10,7 @@ module Phlex
10
10
  #
11
11
  # THE token hot path. Both memos below are bare defined?/||= fast paths
12
12
  # ON PURPOSE: a render must never pay a per-read generation compare
13
- # (issue #115 invariant, .claude/rules/performance.md). Coherence comes
13
+ # (issue #115 invariant, AGENTS.md → Performance). Coherence comes
14
14
  # from the WRITE side instead — Component::Registry.bump! sweeps these
15
15
  # memos off the declaring class and all its descendants whenever any
16
16
  # registry declaration lands (class-load-shaped, rare), so they can't go
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Phlex
4
4
  module Reactive
5
- VERSION = "0.16.2"
5
+ VERSION = "0.16.3"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phlex-reactive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.2
4
+ version: 0.16.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikael Henriksson